From fd5b1583fe3c7e2a866b18a42e9dcde0c647802d Mon Sep 17 00:00:00 2001 From: León Orell Valerian Liehr Date: Fri, 2 May 2025 23:03:30 +0200 Subject: Don't delay a bug on malformed meta items involving interpolated tokens MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Jana Dönszelmann --- compiler/rustc_attr_parsing/src/parser.rs | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) (limited to 'compiler') diff --git a/compiler/rustc_attr_parsing/src/parser.rs b/compiler/rustc_attr_parsing/src/parser.rs index a8a1460591c..e84bac945dc 100644 --- a/compiler/rustc_attr_parsing/src/parser.rs +++ b/compiler/rustc_attr_parsing/src/parser.rs @@ -13,7 +13,7 @@ use rustc_ast_pretty::pprust; use rustc_errors::DiagCtxtHandle; use rustc_hir::{self as hir, AttrPath}; use rustc_span::symbol::{Ident, kw, sym}; -use rustc_span::{ErrorGuaranteed, Span, Symbol}; +use rustc_span::{Span, Symbol}; pub struct SegmentIterator<'a> { offset: usize, @@ -176,7 +176,7 @@ impl<'a> ArgParser<'a> { pub enum MetaItemOrLitParser<'a> { MetaItemParser(MetaItemParser<'a>), Lit(MetaItemLit), - Err(Span, ErrorGuaranteed), + Err(Span), } impl<'a> MetaItemOrLitParser<'a> { @@ -186,7 +186,7 @@ impl<'a> MetaItemOrLitParser<'a> { generic_meta_item_parser.span() } MetaItemOrLitParser::Lit(meta_item_lit) => meta_item_lit.span, - MetaItemOrLitParser::Err(span, _) => *span, + MetaItemOrLitParser::Err(span) => *span, } } @@ -495,12 +495,9 @@ impl<'a> MetaItemListParserContext<'a> { // where the macro didn't expand to a literal. An error is already given // for this at this point, and then we do continue. This makes this path // reachable... - let e = self.dcx.span_delayed_bug( - *span, - "expr in place where literal is expected (builtin attr parsing)", - ); - - return Some(MetaItemOrLitParser::Err(*span, e)); + // NOTE: For backward compatibility we can't emit any error / delayed bug here (yet). + // See + return Some(MetaItemOrLitParser::Err(*span)); } else { self.next_path()? }; -- cgit 1.4.1-3-g733a5 From 2f71d0a243f31f346f868808f8ff5892a8ff8279 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 5 May 2025 19:44:10 +0000 Subject: Only include associated type bounds for Self:Sized associated types if they are provided --- .../src/hir_ty_lowering/dyn_compatibility.rs | 9 ++++---- compiler/rustc_middle/src/ty/sty.rs | 5 ++++- .../object/constrain-via-unnecessary-bound.rs | 24 ++++++++++++++++++++++ .../object/constrain-via-unnecessary-bound.stderr | 19 +++++++++++++++++ tests/ui/traits/object/pretty.stderr | 6 +++--- 5 files changed, 55 insertions(+), 8 deletions(-) create mode 100644 tests/ui/traits/object/constrain-via-unnecessary-bound.rs create mode 100644 tests/ui/traits/object/constrain-via-unnecessary-bound.stderr (limited to 'compiler') diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs index 27643e715e6..19f80751d05 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs @@ -178,9 +178,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { .filter(|item| item.kind == ty::AssocKind::Type) // No RPITITs -- they're not dyn-compatible for now. .filter(|item| !item.is_impl_trait_in_trait()) - // If the associated type has a `where Self: Sized` bound, - // we do not need to constrain the associated type. - .filter(|item| !tcx.generics_require_sized_self(item.def_id)) .map(|item| (item.def_id, trait_ref)), ); } @@ -259,7 +256,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { if let Some(assoc) = projection_bounds.get(&key) { Some(*assoc) } else { - missing_assoc_types.insert(key); + // If the associated type has a `where Self: Sized` bound, + // we do not need to constrain the associated type. + if !tcx.generics_require_sized_self(key.0) { + missing_assoc_types.insert(key); + } None } }) diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 74a94d82784..c7193c6f6df 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -720,7 +720,10 @@ impl<'tcx> Ty<'tcx> { repr: DynKind, ) -> Ty<'tcx> { if cfg!(debug_assertions) { - let projection_count = obj.projection_bounds().count(); + let projection_count = obj + .projection_bounds() + .filter(|item| !tcx.generics_require_sized_self(item.item_def_id())) + .count(); let expected_count: usize = obj .principal_def_id() .into_iter() diff --git a/tests/ui/traits/object/constrain-via-unnecessary-bound.rs b/tests/ui/traits/object/constrain-via-unnecessary-bound.rs new file mode 100644 index 00000000000..5534471fb27 --- /dev/null +++ b/tests/ui/traits/object/constrain-via-unnecessary-bound.rs @@ -0,0 +1,24 @@ +//@ check-pass + +// Regression test for . +// Test that we lower impossible-to-satisfy associated type bounds, which +// may for example constrain impl parameters. + +pub trait Other {} + +pub trait Trait { + type Assoc + where + Self: Sized; +} + +impl Other for dyn Trait {} +// `dyn Trait` is a different "nominal type" than `dyn Traiat`. +impl Other for dyn Trait {} +//~^ WARN unnecessary associated type bound for dyn-incompatible associated type + +// I hope it's clear that `dyn Trait` (w/o `Assoc`) wouldn't match this impl. +impl dyn Trait {} +//~^ WARN unnecessary associated type bound for dyn-incompatible associated type + +fn main() {} diff --git a/tests/ui/traits/object/constrain-via-unnecessary-bound.stderr b/tests/ui/traits/object/constrain-via-unnecessary-bound.stderr new file mode 100644 index 00000000000..4383ca869ea --- /dev/null +++ b/tests/ui/traits/object/constrain-via-unnecessary-bound.stderr @@ -0,0 +1,19 @@ +warning: unnecessary associated type bound for dyn-incompatible associated type + --> $DIR/constrain-via-unnecessary-bound.rs:17:26 + | +LL | impl Other for dyn Trait {} + | ^^^^^^^^^^ help: remove this bound + | + = note: this associated type has a `where Self: Sized` bound, and while the associated type can be specified, it cannot be used because trait objects are never `Sized` + = note: `#[warn(unused_associated_type_bounds)]` on by default + +warning: unnecessary associated type bound for dyn-incompatible associated type + --> $DIR/constrain-via-unnecessary-bound.rs:21:19 + | +LL | impl dyn Trait {} + | ^^^^^^^^^ help: remove this bound + | + = note: this associated type has a `where Self: Sized` bound, and while the associated type can be specified, it cannot be used because trait objects are never `Sized` + +warning: 2 warnings emitted + diff --git a/tests/ui/traits/object/pretty.stderr b/tests/ui/traits/object/pretty.stderr index 37fe142951d..2f9fdf151f0 100644 --- a/tests/ui/traits/object/pretty.stderr +++ b/tests/ui/traits/object/pretty.stderr @@ -154,12 +154,12 @@ error[E0308]: mismatched types --> $DIR/pretty.rs:41:56 | LL | fn dyn_has_gat(x: &dyn HasGat = ()>) { x } - | - ^ expected `()`, found `&dyn HasGat` + | - ^ expected `()`, found `&dyn HasGat = ()>` | | - | help: try adding a return type: `-> &dyn HasGat` + | help: try adding a return type: `-> &dyn HasGat = ()>` | = note: expected unit type `()` - found reference `&dyn HasGat` + found reference `&dyn HasGat = ()>` error: aborting due to 14 previous errors; 1 warning emitted -- cgit 1.4.1-3-g733a5 From d800540c12f6da4f2006ff2b13ea64a6883857bf Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 7 May 2025 16:55:21 +0000 Subject: Review --- .../src/hir_ty_lowering/dyn_compatibility.rs | 25 +++++++++++++++++----- .../object/constrain-via-unnecessary-bound.rs | 2 +- 2 files changed, 21 insertions(+), 6 deletions(-) (limited to 'compiler') diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs index 19f80751d05..8be8ea1cc1c 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs @@ -146,7 +146,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let principal_trait = regular_traits.into_iter().next(); - let mut needed_associated_types = vec![]; + // A stable ordering of associated types from the principal trait and all its + // supertraits. We use this to ensure that different substitutions of a trait + // don't result in `dyn Trait` types with different projections lists, which + // can be unsound: . + // We achieve a stable ordering by walking over the unsubstituted principal + // trait ref. + let mut ordered_associated_types = vec![]; + if let Some((principal_trait, ref spans)) = principal_trait { let principal_trait = principal_trait.map_bound(|trait_pred| { assert_eq!(trait_pred.polarity, ty::PredicatePolarity::Positive); @@ -171,7 +178,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // FIXME(negative_bounds): Handle this correctly... let trait_ref = tcx.anonymize_bound_vars(bound_predicate.rebind(pred.trait_ref)); - needed_associated_types.extend( + ordered_associated_types.extend( tcx.associated_items(pred.trait_ref.def_id) .in_definition_order() // We only care about associated types. @@ -249,15 +256,23 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } } + // We compute the list of projection bounds taking the ordered associated types, + // and check if there was an entry in the collected `projection_bounds`. Those + // are computed by first taking the user-written associated types, then elaborating + // the principal trait ref, and only using those if there was no user-written. + // See note below about how we handle missing associated types with `Self: Sized`, + // which are not required to be provided, but are still used if they are provided. let mut missing_assoc_types = FxIndexSet::default(); - let projection_bounds: Vec<_> = needed_associated_types + let projection_bounds: Vec<_> = ordered_associated_types .into_iter() .filter_map(|key| { if let Some(assoc) = projection_bounds.get(&key) { Some(*assoc) } else { - // If the associated type has a `where Self: Sized` bound, - // we do not need to constrain the associated type. + // If the associated type has a `where Self: Sized` bound, then + // we do not need to provide the associated type. This results in + // a `dyn Trait` type that has a different number of projection + // bounds, which may lead to type mismatches. if !tcx.generics_require_sized_self(key.0) { missing_assoc_types.insert(key); } diff --git a/tests/ui/traits/object/constrain-via-unnecessary-bound.rs b/tests/ui/traits/object/constrain-via-unnecessary-bound.rs index 5534471fb27..4640d6b3ed5 100644 --- a/tests/ui/traits/object/constrain-via-unnecessary-bound.rs +++ b/tests/ui/traits/object/constrain-via-unnecessary-bound.rs @@ -13,7 +13,7 @@ pub trait Trait { } impl Other for dyn Trait {} -// `dyn Trait` is a different "nominal type" than `dyn Traiat`. +// `dyn Trait` is a different "nominal type" than `dyn Trait`. impl Other for dyn Trait {} //~^ WARN unnecessary associated type bound for dyn-incompatible associated type -- cgit 1.4.1-3-g733a5