Skip to content

Commit

Permalink
Auto merge of rust-lang#134651 - matthiaskrgr:rollup-ch58cxz, r=matth…
Browse files Browse the repository at this point in the history
…iaskrgr

Rollup of 4 pull requests

Successful merges:

 - rust-lang#134599 (Detect invalid exprs in parser used by pretty-printer tests)
 - rust-lang#134602 (Document `PointerLike` implementation restrictions.)
 - rust-lang#134635 (Don't ICE on illegal `dyn*` casts)
 - rust-lang#134639 (Make sure we note ambiguity causes on positive/negative impl conflicts)

r? `@ghost`
`@rustbot` modify labels: rollup
  • Loading branch information
bors committed Dec 22, 2024
2 parents a2bcfae + 4d166cc commit bace306
Show file tree
Hide file tree
Showing 13 changed files with 176 additions and 79 deletions.
12 changes: 5 additions & 7 deletions compiler/rustc_hir_typeck/src/cast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -721,13 +721,11 @@ impl<'a, 'tcx> CastCheck<'tcx> {
use rustc_middle::ty::cast::IntTy::*;

if self.cast_ty.is_dyn_star() {
if fcx.tcx.features().dyn_star() {
span_bug!(self.span, "should be handled by `coerce`");
} else {
// Report "casting is invalid" rather than "non-primitive cast"
// if the feature is not enabled.
return Err(CastError::IllegalCast);
}
// This coercion will fail if the feature is not enabled, OR
// if the coercion is (currently) illegal (e.g. `dyn* Foo + Send`
// to `dyn* Foo`). Report "casting is invalid" rather than
// "non-primitive cast".
return Err(CastError::IllegalCast);
}

let (t_from, t_cast) = match (CastTy::from_ty(self.expr_ty), CastTy::from_ty(self.cast_ty))
Expand Down
6 changes: 4 additions & 2 deletions compiler/rustc_hir_typeck/src/coercion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -737,8 +737,10 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
return Err(TypeError::Mismatch);
}

if let ty::Dynamic(a_data, _, _) = a.kind()
&& let ty::Dynamic(b_data, _, _) = b.kind()
// FIXME(dyn_star): We should probably allow things like casting from
// `dyn* Foo + Send` to `dyn* Foo`.
if let ty::Dynamic(a_data, _, ty::DynStar) = a.kind()
&& let ty::Dynamic(b_data, _, ty::DynStar) = b.kind()
&& a_data.principal_def_id() == b_data.principal_def_id()
{
return self.unify_and(a, b, |_| vec![]);
Expand Down
22 changes: 13 additions & 9 deletions compiler/rustc_trait_selection/src/traits/specialize/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -483,15 +483,19 @@ fn report_negative_positive_conflict<'tcx>(
negative_impl_def_id: DefId,
positive_impl_def_id: DefId,
) -> ErrorGuaranteed {
tcx.dcx()
.create_err(NegativePositiveConflict {
impl_span: tcx.def_span(local_impl_def_id),
trait_desc: overlap.trait_ref,
self_ty: overlap.self_ty,
negative_impl_span: tcx.span_of_impl(negative_impl_def_id),
positive_impl_span: tcx.span_of_impl(positive_impl_def_id),
})
.emit()
let mut diag = tcx.dcx().create_err(NegativePositiveConflict {
impl_span: tcx.def_span(local_impl_def_id),
trait_desc: overlap.trait_ref,
self_ty: overlap.self_ty,
negative_impl_span: tcx.span_of_impl(negative_impl_def_id),
positive_impl_span: tcx.span_of_impl(positive_impl_def_id),
});

for cause in &overlap.intercrate_ambiguity_causes {
cause.add_intercrate_ambiguity_hint(&mut diag);
}

diag.emit()
}

fn report_conflicting_impls<'tcx>(
Expand Down
10 changes: 8 additions & 2 deletions library/core/src/marker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -982,8 +982,14 @@ pub trait Tuple {}

/// A marker for pointer-like types.
///
/// This trait can only be implemented for types that have the same size and alignment
/// as a `usize` or `*const ()`.
/// This trait can only be implemented for types that are certain to have
/// the same size and alignment as a [`usize`] or [`*const ()`](pointer).
/// To ensure this, there are special requirements on implementations
/// of `PointerLike` (other than the already-provided implementations
/// for built-in types):
///
/// * The type must have `#[repr(transparent)]`.
/// * The type’s sole non-zero-sized field must itself implement `PointerLike`.
#[unstable(feature = "pointer_like_trait", issue = "none")]
#[lang = "pointer_like"]
#[diagnostic::on_unimplemented(
Expand Down
9 changes: 0 additions & 9 deletions tests/crashes/132127.rs

This file was deleted.

51 changes: 51 additions & 0 deletions tests/ui-fulldeps/auxiliary/parser.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#![feature(rustc_private)]

extern crate rustc_ast;
extern crate rustc_driver;
extern crate rustc_errors;
extern crate rustc_parse;
extern crate rustc_session;
extern crate rustc_span;

use rustc_ast::ast::{DUMMY_NODE_ID, Expr};
use rustc_ast::mut_visit::MutVisitor;
use rustc_ast::node_id::NodeId;
use rustc_ast::ptr::P;
use rustc_ast::token;
use rustc_errors::Diag;
use rustc_parse::parser::Recovery;
use rustc_session::parse::ParseSess;
use rustc_span::{DUMMY_SP, FileName, Span};

pub fn parse_expr(psess: &ParseSess, source_code: &str) -> Option<P<Expr>> {
let parser = rustc_parse::unwrap_or_emit_fatal(rustc_parse::new_parser_from_source_str(
psess,
FileName::anon_source_code(source_code),
source_code.to_owned(),
));

let mut parser = parser.recovery(Recovery::Forbidden);
let mut expr = parser.parse_expr().map_err(Diag::cancel).ok()?;
if parser.token != token::Eof {
return None;
}

Normalize.visit_expr(&mut expr);
Some(expr)
}

// Erase Span information that could distinguish between identical expressions
// parsed from different source strings.
struct Normalize;

impl MutVisitor for Normalize {
const VISIT_TOKENS: bool = true;

fn visit_id(&mut self, id: &mut NodeId) {
*id = DUMMY_NODE_ID;
}

fn visit_span(&mut self, span: &mut Span) {
*span = DUMMY_SP;
}
}
18 changes: 4 additions & 14 deletions tests/ui-fulldeps/pprust-expr-roundtrip.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
//@ run-pass
//@ ignore-cross-compile
//@ aux-crate: parser=parser.rs
//@ edition: 2021

// The general idea of this test is to enumerate all "interesting" expressions and check that
// `parse(print(e)) == e` for all `e`. Here's what's interesting, for the purposes of this test:
Expand All @@ -21,7 +23,6 @@

extern crate rustc_ast;
extern crate rustc_ast_pretty;
extern crate rustc_data_structures;
extern crate rustc_parse;
extern crate rustc_session;
extern crate rustc_span;
Expand All @@ -32,28 +33,17 @@ extern crate thin_vec;
#[allow(unused_extern_crates)]
extern crate rustc_driver;

use parser::parse_expr;
use rustc_ast::mut_visit::{visit_clobber, MutVisitor};
use rustc_ast::ptr::P;
use rustc_ast::*;
use rustc_ast_pretty::pprust;
use rustc_parse::{new_parser_from_source_str, unwrap_or_emit_fatal};
use rustc_session::parse::ParseSess;
use rustc_span::source_map::Spanned;
use rustc_span::symbol::Ident;
use rustc_span::{FileName, DUMMY_SP};
use rustc_span::DUMMY_SP;
use thin_vec::{thin_vec, ThinVec};

fn parse_expr(psess: &ParseSess, src: &str) -> Option<P<Expr>> {
let src_as_string = src.to_string();

let mut p = unwrap_or_emit_fatal(new_parser_from_source_str(
psess,
FileName::Custom(src_as_string.clone()),
src_as_string,
));
p.parse_expr().map_err(|e| e.cancel()).ok()
}

// Helper functions for building exprs
fn expr(kind: ExprKind) -> P<Expr> {
P(Expr { id: DUMMY_NODE_ID, kind, span: DUMMY_SP, attrs: AttrVec::new(), tokens: None })
Expand Down
43 changes: 7 additions & 36 deletions tests/ui-fulldeps/pprust-parenthesis-insertion.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
//@ run-pass
//@ ignore-cross-compile
//@ aux-crate: parser=parser.rs
//@ edition: 2021

// This test covers the AST pretty-printer's automatic insertion of parentheses
// into unparenthesized syntax trees according to precedence and various grammar
Expand Down Expand Up @@ -31,24 +33,19 @@

extern crate rustc_ast;
extern crate rustc_ast_pretty;
extern crate rustc_driver;
extern crate rustc_errors;
extern crate rustc_parse;
extern crate rustc_session;
extern crate rustc_span;

use std::mem;
use std::process::ExitCode;

use rustc_ast::ast::{DUMMY_NODE_ID, Expr, ExprKind};
use parser::parse_expr;
use rustc_ast::ast::{Expr, ExprKind};
use rustc_ast::mut_visit::{self, DummyAstNode as _, MutVisitor};
use rustc_ast::node_id::NodeId;
use rustc_ast::ptr::P;
use rustc_ast_pretty::pprust;
use rustc_errors::Diag;
use rustc_parse::parser::Recovery;
use rustc_session::parse::ParseSess;
use rustc_span::{DUMMY_SP, FileName, Span};

// Every parenthesis in the following expressions is re-inserted by the
// pretty-printer.
Expand Down Expand Up @@ -156,34 +153,6 @@ impl MutVisitor for Unparenthesize {
}
}

// Erase Span information that could distinguish between identical expressions
// parsed from different source strings.
struct Normalize;

impl MutVisitor for Normalize {
const VISIT_TOKENS: bool = true;

fn visit_id(&mut self, id: &mut NodeId) {
*id = DUMMY_NODE_ID;
}

fn visit_span(&mut self, span: &mut Span) {
*span = DUMMY_SP;
}
}

fn parse_expr(psess: &ParseSess, source_code: &str) -> Option<P<Expr>> {
let parser = rustc_parse::unwrap_or_emit_fatal(rustc_parse::new_parser_from_source_str(
psess,
FileName::anon_source_code(source_code),
source_code.to_owned(),
));

let mut expr = parser.recovery(Recovery::Forbidden).parse_expr().map_err(Diag::cancel).ok()?;
Normalize.visit_expr(&mut expr);
Some(expr)
}

fn main() -> ExitCode {
let mut status = ExitCode::SUCCESS;
let mut fail = |description: &str, before: &str, after: &str| {
Expand All @@ -199,7 +168,9 @@ fn main() -> ExitCode {
let psess = &ParseSess::new(vec![rustc_parse::DEFAULT_LOCALE_RESOURCE]);

for &source_code in EXPRS {
let expr = parse_expr(psess, source_code).unwrap();
let Some(expr) = parse_expr(psess, source_code) else {
panic!("Failed to parse original test case: {source_code}");
};

// Check for FALSE POSITIVE: pretty-printer inserting parentheses where not needed.
// Pseudocode:
Expand Down
16 changes: 16 additions & 0 deletions tests/ui/dyn-star/illegal.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#![feature(dyn_star)]
//~^ WARN the feature `dyn_star` is incomplete

trait Foo {}

pub fn lol(x: dyn* Foo + Send) {
x as dyn* Foo;
//~^ ERROR casting `(dyn* Foo + Send + 'static)` as `dyn* Foo` is invalid
}

fn lol2(x: &dyn Foo) {
*x as dyn* Foo;
//~^ ERROR `dyn Foo` needs to have the same ABI as a pointer
}

fn main() {}
27 changes: 27 additions & 0 deletions tests/ui/dyn-star/illegal.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
warning: the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/illegal.rs:1:12
|
LL | #![feature(dyn_star)]
| ^^^^^^^^
|
= note: see issue #102425 <https://github.com/rust-lang/rust/issues/102425> for more information
= note: `#[warn(incomplete_features)]` on by default

error[E0606]: casting `(dyn* Foo + Send + 'static)` as `dyn* Foo` is invalid
--> $DIR/illegal.rs:7:5
|
LL | x as dyn* Foo;
| ^^^^^^^^^^^^^

error[E0277]: `dyn Foo` needs to have the same ABI as a pointer
--> $DIR/illegal.rs:12:5
|
LL | *x as dyn* Foo;
| ^^ `dyn Foo` needs to be a pointer-like type
|
= help: the trait `PointerLike` is not implemented for `dyn Foo`

error: aborting due to 2 previous errors; 1 warning emitted

Some errors have detailed explanations: E0277, E0606.
For more information about an error, try `rustc --explain E0277`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
error[E0119]: conflicting implementations of trait `MyTrait` for type `String`
--> $DIR/ambiguity-cause.rs:10:1
|
LL | impl<T: Copy> MyTrait for T { }
| --------------------------- first implementation here
LL |
LL | impl MyTrait for String { }
| ^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `String`
|
= note: upstream crates may add a new impl of trait `std::marker::Copy` for type `std::string::String` in future versions

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0119`.
13 changes: 13 additions & 0 deletions tests/ui/traits/negative-impls/ambiguity-cause.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//@ revisions: simple negative_coherence

#![feature(negative_impls)]
#![cfg_attr(negative_coherence, feature(with_negative_coherence))]

trait MyTrait {}

impl<T: Copy> MyTrait for T { }

impl MyTrait for String { }
//~^ ERROR conflicting implementations of trait `MyTrait` for type `String`

fn main() {}
14 changes: 14 additions & 0 deletions tests/ui/traits/negative-impls/ambiguity-cause.simple.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
error[E0119]: conflicting implementations of trait `MyTrait` for type `String`
--> $DIR/ambiguity-cause.rs:10:1
|
LL | impl<T: Copy> MyTrait for T { }
| --------------------------- first implementation here
LL |
LL | impl MyTrait for String { }
| ^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `String`
|
= note: upstream crates may add a new impl of trait `std::marker::Copy` for type `std::string::String` in future versions

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0119`.

0 comments on commit bace306

Please sign in to comment.