Skip to content

Commit bace306

Browse files
committed
Auto merge of #134651 - matthiaskrgr:rollup-ch58cxz, r=matthiaskrgr
Rollup of 4 pull requests Successful merges: - #134599 (Detect invalid exprs in parser used by pretty-printer tests) - #134602 (Document `PointerLike` implementation restrictions.) - #134635 (Don't ICE on illegal `dyn*` casts) - #134639 (Make sure we note ambiguity causes on positive/negative impl conflicts) r? `@ghost` `@rustbot` modify labels: rollup
2 parents a2bcfae + 4d166cc commit bace306

File tree

13 files changed

+176
-79
lines changed

13 files changed

+176
-79
lines changed

Diff for: compiler/rustc_hir_typeck/src/cast.rs

+5-7
Original file line numberDiff line numberDiff line change
@@ -721,13 +721,11 @@ impl<'a, 'tcx> CastCheck<'tcx> {
721721
use rustc_middle::ty::cast::IntTy::*;
722722

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

733731
let (t_from, t_cast) = match (CastTy::from_ty(self.expr_ty), CastTy::from_ty(self.cast_ty))

Diff for: compiler/rustc_hir_typeck/src/coercion.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -737,8 +737,10 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
737737
return Err(TypeError::Mismatch);
738738
}
739739

740-
if let ty::Dynamic(a_data, _, _) = a.kind()
741-
&& let ty::Dynamic(b_data, _, _) = b.kind()
740+
// FIXME(dyn_star): We should probably allow things like casting from
741+
// `dyn* Foo + Send` to `dyn* Foo`.
742+
if let ty::Dynamic(a_data, _, ty::DynStar) = a.kind()
743+
&& let ty::Dynamic(b_data, _, ty::DynStar) = b.kind()
742744
&& a_data.principal_def_id() == b_data.principal_def_id()
743745
{
744746
return self.unify_and(a, b, |_| vec![]);

Diff for: compiler/rustc_trait_selection/src/traits/specialize/mod.rs

+13-9
Original file line numberDiff line numberDiff line change
@@ -483,15 +483,19 @@ fn report_negative_positive_conflict<'tcx>(
483483
negative_impl_def_id: DefId,
484484
positive_impl_def_id: DefId,
485485
) -> ErrorGuaranteed {
486-
tcx.dcx()
487-
.create_err(NegativePositiveConflict {
488-
impl_span: tcx.def_span(local_impl_def_id),
489-
trait_desc: overlap.trait_ref,
490-
self_ty: overlap.self_ty,
491-
negative_impl_span: tcx.span_of_impl(negative_impl_def_id),
492-
positive_impl_span: tcx.span_of_impl(positive_impl_def_id),
493-
})
494-
.emit()
486+
let mut diag = tcx.dcx().create_err(NegativePositiveConflict {
487+
impl_span: tcx.def_span(local_impl_def_id),
488+
trait_desc: overlap.trait_ref,
489+
self_ty: overlap.self_ty,
490+
negative_impl_span: tcx.span_of_impl(negative_impl_def_id),
491+
positive_impl_span: tcx.span_of_impl(positive_impl_def_id),
492+
});
493+
494+
for cause in &overlap.intercrate_ambiguity_causes {
495+
cause.add_intercrate_ambiguity_hint(&mut diag);
496+
}
497+
498+
diag.emit()
495499
}
496500

497501
fn report_conflicting_impls<'tcx>(

Diff for: library/core/src/marker.rs

+8-2
Original file line numberDiff line numberDiff line change
@@ -982,8 +982,14 @@ pub trait Tuple {}
982982

983983
/// A marker for pointer-like types.
984984
///
985-
/// This trait can only be implemented for types that have the same size and alignment
986-
/// as a `usize` or `*const ()`.
985+
/// This trait can only be implemented for types that are certain to have
986+
/// the same size and alignment as a [`usize`] or [`*const ()`](pointer).
987+
/// To ensure this, there are special requirements on implementations
988+
/// of `PointerLike` (other than the already-provided implementations
989+
/// for built-in types):
990+
///
991+
/// * The type must have `#[repr(transparent)]`.
992+
/// * The type’s sole non-zero-sized field must itself implement `PointerLike`.
987993
#[unstable(feature = "pointer_like_trait", issue = "none")]
988994
#[lang = "pointer_like"]
989995
#[diagnostic::on_unimplemented(

Diff for: tests/crashes/132127.rs

-9
This file was deleted.

Diff for: tests/ui-fulldeps/auxiliary/parser.rs

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
#![feature(rustc_private)]
2+
3+
extern crate rustc_ast;
4+
extern crate rustc_driver;
5+
extern crate rustc_errors;
6+
extern crate rustc_parse;
7+
extern crate rustc_session;
8+
extern crate rustc_span;
9+
10+
use rustc_ast::ast::{DUMMY_NODE_ID, Expr};
11+
use rustc_ast::mut_visit::MutVisitor;
12+
use rustc_ast::node_id::NodeId;
13+
use rustc_ast::ptr::P;
14+
use rustc_ast::token;
15+
use rustc_errors::Diag;
16+
use rustc_parse::parser::Recovery;
17+
use rustc_session::parse::ParseSess;
18+
use rustc_span::{DUMMY_SP, FileName, Span};
19+
20+
pub fn parse_expr(psess: &ParseSess, source_code: &str) -> Option<P<Expr>> {
21+
let parser = rustc_parse::unwrap_or_emit_fatal(rustc_parse::new_parser_from_source_str(
22+
psess,
23+
FileName::anon_source_code(source_code),
24+
source_code.to_owned(),
25+
));
26+
27+
let mut parser = parser.recovery(Recovery::Forbidden);
28+
let mut expr = parser.parse_expr().map_err(Diag::cancel).ok()?;
29+
if parser.token != token::Eof {
30+
return None;
31+
}
32+
33+
Normalize.visit_expr(&mut expr);
34+
Some(expr)
35+
}
36+
37+
// Erase Span information that could distinguish between identical expressions
38+
// parsed from different source strings.
39+
struct Normalize;
40+
41+
impl MutVisitor for Normalize {
42+
const VISIT_TOKENS: bool = true;
43+
44+
fn visit_id(&mut self, id: &mut NodeId) {
45+
*id = DUMMY_NODE_ID;
46+
}
47+
48+
fn visit_span(&mut self, span: &mut Span) {
49+
*span = DUMMY_SP;
50+
}
51+
}

Diff for: tests/ui-fulldeps/pprust-expr-roundtrip.rs

+4-14
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
//@ run-pass
22
//@ ignore-cross-compile
3+
//@ aux-crate: parser=parser.rs
4+
//@ edition: 2021
35

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

2224
extern crate rustc_ast;
2325
extern crate rustc_ast_pretty;
24-
extern crate rustc_data_structures;
2526
extern crate rustc_parse;
2627
extern crate rustc_session;
2728
extern crate rustc_span;
@@ -32,28 +33,17 @@ extern crate thin_vec;
3233
#[allow(unused_extern_crates)]
3334
extern crate rustc_driver;
3435

36+
use parser::parse_expr;
3537
use rustc_ast::mut_visit::{visit_clobber, MutVisitor};
3638
use rustc_ast::ptr::P;
3739
use rustc_ast::*;
3840
use rustc_ast_pretty::pprust;
39-
use rustc_parse::{new_parser_from_source_str, unwrap_or_emit_fatal};
4041
use rustc_session::parse::ParseSess;
4142
use rustc_span::source_map::Spanned;
4243
use rustc_span::symbol::Ident;
43-
use rustc_span::{FileName, DUMMY_SP};
44+
use rustc_span::DUMMY_SP;
4445
use thin_vec::{thin_vec, ThinVec};
4546

46-
fn parse_expr(psess: &ParseSess, src: &str) -> Option<P<Expr>> {
47-
let src_as_string = src.to_string();
48-
49-
let mut p = unwrap_or_emit_fatal(new_parser_from_source_str(
50-
psess,
51-
FileName::Custom(src_as_string.clone()),
52-
src_as_string,
53-
));
54-
p.parse_expr().map_err(|e| e.cancel()).ok()
55-
}
56-
5747
// Helper functions for building exprs
5848
fn expr(kind: ExprKind) -> P<Expr> {
5949
P(Expr { id: DUMMY_NODE_ID, kind, span: DUMMY_SP, attrs: AttrVec::new(), tokens: None })

Diff for: tests/ui-fulldeps/pprust-parenthesis-insertion.rs

+7-36
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
//@ run-pass
22
//@ ignore-cross-compile
3+
//@ aux-crate: parser=parser.rs
4+
//@ edition: 2021
35

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

3234
extern crate rustc_ast;
3335
extern crate rustc_ast_pretty;
34-
extern crate rustc_driver;
35-
extern crate rustc_errors;
3636
extern crate rustc_parse;
3737
extern crate rustc_session;
3838
extern crate rustc_span;
3939

4040
use std::mem;
4141
use std::process::ExitCode;
4242

43-
use rustc_ast::ast::{DUMMY_NODE_ID, Expr, ExprKind};
43+
use parser::parse_expr;
44+
use rustc_ast::ast::{Expr, ExprKind};
4445
use rustc_ast::mut_visit::{self, DummyAstNode as _, MutVisitor};
45-
use rustc_ast::node_id::NodeId;
4646
use rustc_ast::ptr::P;
4747
use rustc_ast_pretty::pprust;
48-
use rustc_errors::Diag;
49-
use rustc_parse::parser::Recovery;
5048
use rustc_session::parse::ParseSess;
51-
use rustc_span::{DUMMY_SP, FileName, Span};
5249

5350
// Every parenthesis in the following expressions is re-inserted by the
5451
// pretty-printer.
@@ -156,34 +153,6 @@ impl MutVisitor for Unparenthesize {
156153
}
157154
}
158155

159-
// Erase Span information that could distinguish between identical expressions
160-
// parsed from different source strings.
161-
struct Normalize;
162-
163-
impl MutVisitor for Normalize {
164-
const VISIT_TOKENS: bool = true;
165-
166-
fn visit_id(&mut self, id: &mut NodeId) {
167-
*id = DUMMY_NODE_ID;
168-
}
169-
170-
fn visit_span(&mut self, span: &mut Span) {
171-
*span = DUMMY_SP;
172-
}
173-
}
174-
175-
fn parse_expr(psess: &ParseSess, source_code: &str) -> Option<P<Expr>> {
176-
let parser = rustc_parse::unwrap_or_emit_fatal(rustc_parse::new_parser_from_source_str(
177-
psess,
178-
FileName::anon_source_code(source_code),
179-
source_code.to_owned(),
180-
));
181-
182-
let mut expr = parser.recovery(Recovery::Forbidden).parse_expr().map_err(Diag::cancel).ok()?;
183-
Normalize.visit_expr(&mut expr);
184-
Some(expr)
185-
}
186-
187156
fn main() -> ExitCode {
188157
let mut status = ExitCode::SUCCESS;
189158
let mut fail = |description: &str, before: &str, after: &str| {
@@ -199,7 +168,9 @@ fn main() -> ExitCode {
199168
let psess = &ParseSess::new(vec![rustc_parse::DEFAULT_LOCALE_RESOURCE]);
200169

201170
for &source_code in EXPRS {
202-
let expr = parse_expr(psess, source_code).unwrap();
171+
let Some(expr) = parse_expr(psess, source_code) else {
172+
panic!("Failed to parse original test case: {source_code}");
173+
};
203174

204175
// Check for FALSE POSITIVE: pretty-printer inserting parentheses where not needed.
205176
// Pseudocode:

Diff for: tests/ui/dyn-star/illegal.rs

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#![feature(dyn_star)]
2+
//~^ WARN the feature `dyn_star` is incomplete
3+
4+
trait Foo {}
5+
6+
pub fn lol(x: dyn* Foo + Send) {
7+
x as dyn* Foo;
8+
//~^ ERROR casting `(dyn* Foo + Send + 'static)` as `dyn* Foo` is invalid
9+
}
10+
11+
fn lol2(x: &dyn Foo) {
12+
*x as dyn* Foo;
13+
//~^ ERROR `dyn Foo` needs to have the same ABI as a pointer
14+
}
15+
16+
fn main() {}

Diff for: tests/ui/dyn-star/illegal.stderr

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
warning: the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes
2+
--> $DIR/illegal.rs:1:12
3+
|
4+
LL | #![feature(dyn_star)]
5+
| ^^^^^^^^
6+
|
7+
= note: see issue #102425 <https://github.com/rust-lang/rust/issues/102425> for more information
8+
= note: `#[warn(incomplete_features)]` on by default
9+
10+
error[E0606]: casting `(dyn* Foo + Send + 'static)` as `dyn* Foo` is invalid
11+
--> $DIR/illegal.rs:7:5
12+
|
13+
LL | x as dyn* Foo;
14+
| ^^^^^^^^^^^^^
15+
16+
error[E0277]: `dyn Foo` needs to have the same ABI as a pointer
17+
--> $DIR/illegal.rs:12:5
18+
|
19+
LL | *x as dyn* Foo;
20+
| ^^ `dyn Foo` needs to be a pointer-like type
21+
|
22+
= help: the trait `PointerLike` is not implemented for `dyn Foo`
23+
24+
error: aborting due to 2 previous errors; 1 warning emitted
25+
26+
Some errors have detailed explanations: E0277, E0606.
27+
For more information about an error, try `rustc --explain E0277`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
error[E0119]: conflicting implementations of trait `MyTrait` for type `String`
2+
--> $DIR/ambiguity-cause.rs:10:1
3+
|
4+
LL | impl<T: Copy> MyTrait for T { }
5+
| --------------------------- first implementation here
6+
LL |
7+
LL | impl MyTrait for String { }
8+
| ^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `String`
9+
|
10+
= note: upstream crates may add a new impl of trait `std::marker::Copy` for type `std::string::String` in future versions
11+
12+
error: aborting due to 1 previous error
13+
14+
For more information about this error, try `rustc --explain E0119`.

Diff for: tests/ui/traits/negative-impls/ambiguity-cause.rs

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
//@ revisions: simple negative_coherence
2+
3+
#![feature(negative_impls)]
4+
#![cfg_attr(negative_coherence, feature(with_negative_coherence))]
5+
6+
trait MyTrait {}
7+
8+
impl<T: Copy> MyTrait for T { }
9+
10+
impl MyTrait for String { }
11+
//~^ ERROR conflicting implementations of trait `MyTrait` for type `String`
12+
13+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
error[E0119]: conflicting implementations of trait `MyTrait` for type `String`
2+
--> $DIR/ambiguity-cause.rs:10:1
3+
|
4+
LL | impl<T: Copy> MyTrait for T { }
5+
| --------------------------- first implementation here
6+
LL |
7+
LL | impl MyTrait for String { }
8+
| ^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `String`
9+
|
10+
= note: upstream crates may add a new impl of trait `std::marker::Copy` for type `std::string::String` in future versions
11+
12+
error: aborting due to 1 previous error
13+
14+
For more information about this error, try `rustc --explain E0119`.

0 commit comments

Comments
 (0)