diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 523001381864d..2d03c854bd088 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -373,6 +373,7 @@ impl<'hir> LoweringContext<'_, 'hir> { (trait_ref, lowered_ty) }); + self.is_in_trait_impl = trait_ref.is_some(); let new_impl_items = self .arena .alloc_from_iter(impl_items.iter().map(|item| self.lower_impl_item_ref(item))); @@ -978,13 +979,6 @@ impl<'hir> LoweringContext<'_, 'hir> { } fn lower_impl_item_ref(&mut self, i: &AssocItem) -> hir::ImplItemRef { - let trait_item_def_id = self - .resolver - .get_partial_res(i.id) - .map(|r| r.expect_full_res().opt_def_id()) - .unwrap_or(None); - self.is_in_trait_impl = trait_item_def_id.is_some(); - hir::ImplItemRef { id: hir::ImplItemId { owner_id: hir::OwnerId { def_id: self.local_def_id(i.id) } }, ident: self.lower_ident(i.ident), @@ -1000,7 +994,11 @@ impl<'hir> LoweringContext<'_, 'hir> { }, AssocItemKind::MacCall(..) => unimplemented!(), }, - trait_item_def_id, + trait_item_def_id: self + .resolver + .get_partial_res(i.id) + .map(|r| r.expect_full_res().opt_def_id()) + .unwrap_or(None), } } diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 2bef4c9122456..3edb832b9a09b 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -1527,6 +1527,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { generics, body.as_deref(), ); + walk_list!(self, visit_attribute, &item.attrs); self.visit_fn(kind, item.span, item.id); } AssocItemKind::Type(_) => { diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index bad472dcb5c06..1c68de51ba6a0 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -351,6 +351,7 @@ hir_analysis_rpitit_refined = impl trait in impl method signature does not match .label = return type from trait method defined here .unmatched_bound_label = this bound is stronger than that defined on the trait .note = add `#[allow(refining_impl_trait)]` if it is intended for this to be part of the public API of this crate + .feedback_note = we are soliciting feedback, see issue #121718 for more information hir_analysis_self_in_impl_self = `Self` is not valid in the self type of an impl block diff --git a/compiler/rustc_hir_analysis/src/astconv/bounds.rs b/compiler/rustc_hir_analysis/src/astconv/bounds.rs index 17e0aeb044cf8..c6942b0f4567b 100644 --- a/compiler/rustc_hir_analysis/src/astconv/bounds.rs +++ b/compiler/rustc_hir_analysis/src/astconv/bounds.rs @@ -149,7 +149,6 @@ impl<'tcx> dyn AstConv<'tcx> + '_ { polarity, param_ty, bounds, - false, only_self_bounds, ); } @@ -231,14 +230,13 @@ impl<'tcx> dyn AstConv<'tcx> + '_ { /// **A note on binders:** given something like `T: for<'a> Iterator`, the /// `trait_ref` here will be `for<'a> T: Iterator`. The `binding` data however is from *inside* /// the binder (e.g., `&'a u32`) and hence may reference bound regions. - #[instrument(level = "debug", skip(self, bounds, speculative, dup_bindings, path_span))] + #[instrument(level = "debug", skip(self, bounds, dup_bindings, path_span))] pub(super) fn add_predicates_for_ast_type_binding( &self, hir_ref_id: hir::HirId, trait_ref: ty::PolyTraitRef<'tcx>, binding: &hir::TypeBinding<'tcx>, bounds: &mut Bounds<'tcx>, - speculative: bool, dup_bindings: &mut FxIndexMap, path_span: Span, only_self_bounds: OnlySelfBounds, @@ -317,19 +315,17 @@ impl<'tcx> dyn AstConv<'tcx> + '_ { } tcx.check_stability(assoc_item.def_id, Some(hir_ref_id), binding.span, None); - if !speculative { - dup_bindings - .entry(assoc_item.def_id) - .and_modify(|prev_span| { - tcx.dcx().emit_err(errors::ValueOfAssociatedStructAlreadySpecified { - span: binding.span, - prev_span: *prev_span, - item_name: binding.ident, - def_path: tcx.def_path_str(assoc_item.container_id(tcx)), - }); - }) - .or_insert(binding.span); - } + dup_bindings + .entry(assoc_item.def_id) + .and_modify(|prev_span| { + tcx.dcx().emit_err(errors::ValueOfAssociatedStructAlreadySpecified { + span: binding.span, + prev_span: *prev_span, + item_name: binding.ident, + def_path: tcx.def_path_str(assoc_item.container_id(tcx)), + }); + }) + .or_insert(binding.span); let projection_ty = if let ty::AssocKind::Fn = assoc_kind { let mut emitted_bad_param_err = None; @@ -433,9 +429,8 @@ impl<'tcx> dyn AstConv<'tcx> + '_ { }); // Provide the resolved type of the associated constant to `type_of(AnonConst)`. - if !speculative - && let hir::TypeBindingKind::Equality { term: hir::Term::Const(anon_const) } = - binding.kind + if let hir::TypeBindingKind::Equality { term: hir::Term::Const(anon_const) } = + binding.kind { let ty = alias_ty.map_bound(|ty| tcx.type_of(ty.def_id).instantiate(tcx, ty.args)); // Since the arguments passed to the alias type above may contain early-bound @@ -463,42 +458,40 @@ impl<'tcx> dyn AstConv<'tcx> + '_ { hir::Term::Const(ct) => ty::Const::from_anon_const(tcx, ct.def_id).into(), }; - if !speculative { - // Find any late-bound regions declared in `ty` that are not - // declared in the trait-ref or assoc_item. These are not well-formed. - // - // Example: - // - // for<'a> ::Item = &'a str // <-- 'a is bad - // for<'a> >::Output = &'a str // <-- 'a is ok - let late_bound_in_projection_ty = - tcx.collect_constrained_late_bound_regions(projection_ty); - let late_bound_in_term = - tcx.collect_referenced_late_bound_regions(trait_ref.rebind(term)); - debug!(?late_bound_in_projection_ty); - debug!(?late_bound_in_term); + // Find any late-bound regions declared in `ty` that are not + // declared in the trait-ref or assoc_item. These are not well-formed. + // + // Example: + // + // for<'a> ::Item = &'a str // <-- 'a is bad + // for<'a> >::Output = &'a str // <-- 'a is ok + let late_bound_in_projection_ty = + tcx.collect_constrained_late_bound_regions(projection_ty); + let late_bound_in_term = + tcx.collect_referenced_late_bound_regions(trait_ref.rebind(term)); + debug!(?late_bound_in_projection_ty); + debug!(?late_bound_in_term); - // FIXME: point at the type params that don't have appropriate lifetimes: - // struct S1 Fn(&i32, &i32) -> &'a i32>(F); - // ---- ---- ^^^^^^^ - // NOTE(associated_const_equality): This error should be impossible to trigger - // with associated const equality bounds. - self.validate_late_bound_regions( - late_bound_in_projection_ty, - late_bound_in_term, - |br_name| { - struct_span_code_err!( - tcx.dcx(), - binding.span, - E0582, - "binding for associated type `{}` references {}, \ - which does not appear in the trait input types", - binding.ident, - br_name - ) - }, - ); - } + // FIXME: point at the type params that don't have appropriate lifetimes: + // struct S1 Fn(&i32, &i32) -> &'a i32>(F); + // ---- ---- ^^^^^^^ + // NOTE(associated_const_equality): This error should be impossible to trigger + // with associated const equality bounds. + self.validate_late_bound_regions( + late_bound_in_projection_ty, + late_bound_in_term, + |br_name| { + struct_span_code_err!( + tcx.dcx(), + binding.span, + E0582, + "binding for associated type `{}` references {}, \ + which does not appear in the trait input types", + binding.ident, + br_name + ) + }, + ); // "Desugar" a constraint like `T: Iterator` this to // the "projection predicate" for: diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 401dd76a9f914..a912d7f578dd0 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -639,7 +639,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ { /// where `'a` is a bound region at depth 0. Similarly, the `poly_trait_ref` would be /// `Bar<'a>`. The returned poly-trait-ref will have this binder instantiated explicitly, /// however. - #[instrument(level = "debug", skip(self, span, constness, bounds, speculative))] + #[instrument(level = "debug", skip(self, span, constness, bounds))] pub(crate) fn instantiate_poly_trait_ref( &self, trait_ref: &hir::TraitRef<'tcx>, @@ -648,7 +648,6 @@ impl<'tcx> dyn AstConv<'tcx> + '_ { polarity: ty::ImplPolarity, self_ty: Ty<'tcx>, bounds: &mut Bounds<'tcx>, - speculative: bool, only_self_bounds: OnlySelfBounds, ) -> GenericArgCountResult { let trait_def_id = trait_ref.trait_def_id().unwrap_or_else(|| FatalError.raise()); @@ -697,7 +696,6 @@ impl<'tcx> dyn AstConv<'tcx> + '_ { poly_trait_ref, binding, bounds, - speculative, &mut dup_bindings, binding.span, only_self_bounds, diff --git a/compiler/rustc_hir_analysis/src/astconv/object_safety.rs b/compiler/rustc_hir_analysis/src/astconv/object_safety.rs index d97728c33035d..70c60e3994188 100644 --- a/compiler/rustc_hir_analysis/src/astconv/object_safety.rs +++ b/compiler/rustc_hir_analysis/src/astconv/object_safety.rs @@ -44,7 +44,6 @@ impl<'tcx> dyn AstConv<'tcx> + '_ { ty::ImplPolarity::Positive, dummy_self, &mut bounds, - false, // True so we don't populate `bounds` with associated type bounds, even // though they're disallowed from object types. OnlySelfBounds(true), diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs index 8c4c4fc774ec8..a2a20082bb03e 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs @@ -2,7 +2,7 @@ use rustc_data_structures::fx::FxIndexSet; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_infer::infer::{outlives::env::OutlivesEnvironment, TyCtxtInferExt}; -use rustc_lint_defs::builtin::REFINING_IMPL_TRAIT; +use rustc_lint_defs::builtin::{REFINING_IMPL_TRAIT_INTERNAL, REFINING_IMPL_TRAIT_REACHABLE}; use rustc_middle::traits::{ObligationCause, Reveal}; use rustc_middle::ty::{ self, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperVisitable, TypeVisitable, TypeVisitor, @@ -23,26 +23,23 @@ pub(super) fn check_refining_return_position_impl_trait_in_trait<'tcx>( if !tcx.impl_method_has_trait_impl_trait_tys(impl_m.def_id) { return; } + // unreachable traits don't have any library guarantees, there's no need to do this check. - if trait_m + let is_internal = trait_m .container_id(tcx) .as_local() .is_some_and(|trait_def_id| !tcx.effective_visibilities(()).is_reachable(trait_def_id)) - { - return; - } + // If a type in the trait ref is private, then there's also no reason to do this check. + || impl_trait_ref.args.iter().any(|arg| { + if let Some(ty) = arg.as_type() + && let Some(self_visibility) = type_visibility(tcx, ty) + { + return !self_visibility.is_public(); + } + false + }); - // If a type in the trait ref is private, then there's also no reason to do this check. let impl_def_id = impl_m.container_id(tcx); - for arg in impl_trait_ref.args { - if let Some(ty) = arg.as_type() - && let Some(self_visibility) = type_visibility(tcx, ty) - && !self_visibility.is_public() - { - return; - } - } - let impl_m_args = ty::GenericArgs::identity_for_item(tcx, impl_m.def_id); let trait_m_to_impl_m_args = impl_m_args.rebase_onto(tcx, impl_def_id, impl_trait_ref.args); let bound_trait_m_sig = tcx.fn_sig(trait_m.def_id).instantiate(tcx, trait_m_to_impl_m_args); @@ -85,6 +82,7 @@ pub(super) fn check_refining_return_position_impl_trait_in_trait<'tcx>( trait_m.def_id, impl_m.def_id, None, + is_internal, ); return; }; @@ -104,6 +102,7 @@ pub(super) fn check_refining_return_position_impl_trait_in_trait<'tcx>( trait_m.def_id, impl_m.def_id, None, + is_internal, ); return; } @@ -198,6 +197,7 @@ pub(super) fn check_refining_return_position_impl_trait_in_trait<'tcx>( trait_m.def_id, impl_m.def_id, Some(span), + is_internal, ); return; } @@ -235,6 +235,7 @@ fn report_mismatched_rpitit_signature<'tcx>( trait_m_def_id: DefId, impl_m_def_id: DefId, unmatched_bound: Option, + is_internal: bool, ) { let mapping = std::iter::zip( tcx.fn_sig(trait_m_def_id).skip_binder().bound_vars(), @@ -287,7 +288,7 @@ fn report_mismatched_rpitit_signature<'tcx>( let span = unmatched_bound.unwrap_or(span); tcx.emit_node_span_lint( - REFINING_IMPL_TRAIT, + if is_internal { REFINING_IMPL_TRAIT_INTERNAL } else { REFINING_IMPL_TRAIT_REACHABLE }, tcx.local_def_id_to_hir_id(impl_m_def_id.expect_local()), span, crate::errors::ReturnPositionImplTraitInTraitRefined { diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index 175991b1be266..7bf87f444db29 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -1072,6 +1072,7 @@ pub struct UnusedAssociatedTypeBounds { #[derive(LintDiagnostic)] #[diag(hir_analysis_rpitit_refined)] #[note] +#[note(hir_analysis_feedback_note)] pub(crate) struct ReturnPositionImplTraitInTraitRefined<'tcx> { #[suggestion(applicability = "maybe-incorrect", code = "{pre}{return_ty}{post}")] pub impl_return_span: Span, diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index 250c4adb948e2..31c80c4d75bb1 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -313,6 +313,12 @@ fn register_builtins(store: &mut LintStore) { // MACRO_USE_EXTERN_CRATE ); + add_lint_group!( + "refining_impl_trait", + REFINING_IMPL_TRAIT_REACHABLE, + REFINING_IMPL_TRAIT_INTERNAL + ); + // Register renamed and removed lints. store.register_renamed("single_use_lifetime", "single_use_lifetimes"); store.register_renamed("elided_lifetime_in_path", "elided_lifetimes_in_paths"); diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 6506aa3343108..9f09f46ea5a9c 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -79,7 +79,8 @@ declare_lint_pass! { PROC_MACRO_BACK_COMPAT, PROC_MACRO_DERIVE_RESOLUTION_FALLBACK, PUB_USE_OF_PRIVATE_EXTERN_CRATE, - REFINING_IMPL_TRAIT, + REFINING_IMPL_TRAIT_INTERNAL, + REFINING_IMPL_TRAIT_REACHABLE, RENAMED_AND_REMOVED_LINTS, REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS, RUST_2021_INCOMPATIBLE_CLOSURE_CAPTURES, @@ -130,6 +131,7 @@ declare_lint_pass! { UNUSED_VARIABLES, USELESS_DEPRECATED, WARNINGS, + WASM_C_ABI, WHERE_CLAUSES_OBJECT_SAFETY, WRITES_THROUGH_IMMUTABLE_POINTER, // tidy-alphabetical-end @@ -4401,8 +4403,10 @@ declare_lint! { } declare_lint! { - /// The `refining_impl_trait` lint detects usages of return-position impl - /// traits in trait signatures which are refined by implementations. + /// The `refining_impl_trait_reachable` lint detects `impl Trait` return + /// types in method signatures that are refined by a publically reachable + /// trait implementation, meaning the implementation adds information about + /// the return type that is not present in the trait. /// /// ### Example /// @@ -4424,7 +4428,7 @@ declare_lint! { /// fn main() { /// // users can observe that the return type of /// // `<&str as AsDisplay>::as_display()` is `&str`. - /// let x: &str = "".as_display(); + /// let _x: &str = "".as_display(); /// } /// ``` /// @@ -4432,13 +4436,80 @@ declare_lint! { /// /// ### Explanation /// - /// Return-position impl trait in traits (RPITITs) desugar to associated types, - /// and callers of methods for types where the implementation is known are + /// Callers of methods for types where the implementation is known are /// able to observe the types written in the impl signature. This may be - /// intended behavior, but may also pose a semver hazard for authors of libraries - /// who do not wish to make stronger guarantees about the types than what is - /// written in the trait signature. - pub REFINING_IMPL_TRAIT, + /// intended behavior, but may also lead to implementation details being + /// revealed unintentionally. In particular, it may pose a semver hazard + /// for authors of libraries who do not wish to make stronger guarantees + /// about the types than what is written in the trait signature. + /// + /// `refining_impl_trait` is a lint group composed of two lints: + /// + /// * `refining_impl_trait_reachable`, for refinements that are publically + /// reachable outside a crate, and + /// * `refining_impl_trait_internal`, for refinements that are only visible + /// within a crate. + /// + /// We are seeking feedback on each of these lints; see issue + /// [#121718](https://github.com/rust-lang/rust/issues/121718) for more + /// information. + pub REFINING_IMPL_TRAIT_REACHABLE, + Warn, + "impl trait in impl method signature does not match trait method signature", +} + +declare_lint! { + /// The `refining_impl_trait_internal` lint detects `impl Trait` return + /// types in method signatures that are refined by a trait implementation, + /// meaning the implementation adds information about the return type that + /// is not present in the trait. + /// + /// ### Example + /// + /// ```rust,compile_fail + /// #![deny(refining_impl_trait)] + /// + /// use std::fmt::Display; + /// + /// trait AsDisplay { + /// fn as_display(&self) -> impl Display; + /// } + /// + /// impl<'s> AsDisplay for &'s str { + /// fn as_display(&self) -> Self { + /// *self + /// } + /// } + /// + /// fn main() { + /// // users can observe that the return type of + /// // `<&str as AsDisplay>::as_display()` is `&str`. + /// let _x: &str = "".as_display(); + /// } + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// Callers of methods for types where the implementation is known are + /// able to observe the types written in the impl signature. This may be + /// intended behavior, but may also lead to implementation details being + /// revealed unintentionally. In particular, it may pose a semver hazard + /// for authors of libraries who do not wish to make stronger guarantees + /// about the types than what is written in the trait signature. + /// + /// `refining_impl_trait` is a lint group composed of two lints: + /// + /// * `refining_impl_trait_reachable`, for refinements that are publically + /// reachable outside a crate, and + /// * `refining_impl_trait_internal`, for refinements that are only visible + /// within a crate. + /// + /// We are seeking feedback on each of these lints; see issue + /// [#121718](https://github.com/rust-lang/rust/issues/121718) for more + /// information. + pub REFINING_IMPL_TRAIT_INTERNAL, Warn, "impl trait in impl method signature does not match trait method signature", } @@ -4564,3 +4635,41 @@ declare_lint! { reference: "issue #120192 ", }; } + +declare_lint! { + /// The `wasm_c_abi` lint detects crate dependencies that are incompatible + /// with future versions of Rust that will emit spec-compliant C ABI. + /// + /// ### Example + /// + /// ```rust,ignore (needs extern crate) + /// #![deny(wasm_c_abi)] + /// ``` + /// + /// This will produce: + /// + /// ```text + /// error: the following packages contain code that will be rejected by a future version of Rust: wasm-bindgen v0.2.87 + /// | + /// note: the lint level is defined here + /// --> src/lib.rs:1:9 + /// | + /// 1 | #![deny(wasm_c_abi)] + /// | ^^^^^^^^^^ + /// ``` + /// + /// ### Explanation + /// + /// Rust has historically emitted non-spec-compliant C ABI. This has caused + /// incompatibilities between other compilers and Wasm targets. In a future + /// version of Rust this will be fixed and therefore dependencies relying + /// on the non-spec-compliant C ABI will stop functioning. + pub WASM_C_ABI, + Warn, + "detects dependencies that are incompatible with the Wasm C ABI", + @future_incompatible = FutureIncompatibleInfo { + reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps, + reference: "issue #71871 ", + }; + crate_level_only +} diff --git a/compiler/rustc_metadata/messages.ftl b/compiler/rustc_metadata/messages.ftl index a1c6fba4d435e..f456dd09dea53 100644 --- a/compiler/rustc_metadata/messages.ftl +++ b/compiler/rustc_metadata/messages.ftl @@ -281,6 +281,8 @@ metadata_unsupported_abi = metadata_unsupported_abi_i686 = ABI not supported by `#[link(kind = "raw-dylib")]` on i686 +metadata_wasm_c_abi = + older versions of the `wasm-bindgen` crate will be incompatible with future versions of Rust; please update to `wasm-bindgen` v0.2.88 metadata_wasm_import_form = wasm import module must be of the form `wasm_import_module = "string"` diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index 72757d90e4238..b544bc8a782c4 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -31,8 +31,9 @@ use proc_macro::bridge::client::ProcMacro; use std::error::Error; use std::ops::Fn; use std::path::Path; +use std::str::FromStr; use std::time::Duration; -use std::{cmp, iter}; +use std::{cmp, env, iter}; /// The backend's way to give the crate store access to the metadata in a library. /// Note that it returns the raw metadata bytes stored in the library file, whether @@ -397,7 +398,8 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { name: Symbol, private_dep: Option, ) -> Result { - let _prof_timer = self.sess.prof.generic_activity("metadata_register_crate"); + let _prof_timer = + self.sess.prof.generic_activity_with_arg("metadata_register_crate", name.as_str()); let Library { source, metadata } = lib; let crate_root = metadata.get_root(); @@ -985,6 +987,44 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { } } + fn report_future_incompatible_deps(&self, krate: &ast::Crate) { + let name = self.tcx.crate_name(LOCAL_CRATE); + + if name.as_str() == "wasm_bindgen" { + let major = env::var("CARGO_PKG_VERSION_MAJOR") + .ok() + .and_then(|major| u64::from_str(&major).ok()); + let minor = env::var("CARGO_PKG_VERSION_MINOR") + .ok() + .and_then(|minor| u64::from_str(&minor).ok()); + let patch = env::var("CARGO_PKG_VERSION_PATCH") + .ok() + .and_then(|patch| u64::from_str(&patch).ok()); + + match (major, minor, patch) { + // v1 or bigger is valid. + (Some(1..), _, _) => return, + // v0.3 or bigger is valid. + (Some(0), Some(3..), _) => return, + // v0.2.88 or bigger is valid. + (Some(0), Some(2), Some(88..)) => return, + // Not using Cargo. + (None, None, None) => return, + _ => (), + } + + // Make a point span rather than covering the whole file + let span = krate.spans.inner_span.shrink_to_lo(); + + self.sess.psess.buffer_lint( + lint::builtin::WASM_C_ABI, + span, + ast::CRATE_NODE_ID, + crate::fluent_generated::metadata_wasm_c_abi, + ); + } + } + pub fn postprocess(&mut self, krate: &ast::Crate) { self.inject_forced_externs(); self.inject_profiler_runtime(krate); @@ -992,6 +1032,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { self.inject_panic_runtime(krate); self.report_unused_deps(krate); + self.report_future_incompatible_deps(krate); info!("{:?}", CrateDump(self.cstore)); } diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index 30af752236846..1f0204daf7238 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -1114,7 +1114,7 @@ const unsafe fn swap_nonoverlapping_simple_untyped(x: *mut T, y: *mut T, coun #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_replace", issue = "83164")] #[rustc_diagnostic_item = "ptr_replace"] -pub const unsafe fn replace(dst: *mut T, mut src: T) -> T { +pub const unsafe fn replace(dst: *mut T, src: T) -> T { // SAFETY: the caller must guarantee that `dst` is valid to be // cast to a mutable reference (valid for writes, aligned, initialized), // and cannot overlap `src` since `dst` must point to a distinct @@ -1128,9 +1128,8 @@ pub const unsafe fn replace(dst: *mut T, mut src: T) -> T { align: usize = align_of::(), ) => is_aligned_and_not_null(addr, align) ); - mem::swap(&mut *dst, &mut src); // cannot overlap + mem::replace(&mut *dst, src) } - src } /// Reads the value from `src` without moving it. This leaves the diff --git a/src/tools/lint-docs/src/groups.rs b/src/tools/lint-docs/src/groups.rs index c5cd30ccc3437..0c39f2fa6010f 100644 --- a/src/tools/lint-docs/src/groups.rs +++ b/src/tools/lint-docs/src/groups.rs @@ -16,6 +16,10 @@ static GROUP_DESCRIPTIONS: &[(&str, &str)] = &[ ("rust-2018-compatibility", "Lints used to transition code from the 2015 edition to 2018"), ("rust-2021-compatibility", "Lints used to transition code from the 2018 edition to 2021"), ("rust-2024-compatibility", "Lints used to transition code from the 2021 edition to 2024"), + ( + "refining-impl-trait", + "Detects refinement of `impl Trait` return types by trait implementations", + ), ]; type LintGroups = BTreeMap>; diff --git a/tests/run-make/long-linker-command-lines/Makefile b/tests/run-make/long-linker-command-lines/Makefile index f864ea74f4a95..b573038e344aa 100644 --- a/tests/run-make/long-linker-command-lines/Makefile +++ b/tests/run-make/long-linker-command-lines/Makefile @@ -1,6 +1,8 @@ # ignore-cross-compile include ../tools.mk +export LD_LIBRARY_PATH := $(HOST_RPATH_DIR) + all: $(RUSTC) foo.rs -g -O RUSTC="$(RUSTC_ORIGINAL)" $(call RUN,foo) diff --git a/tests/ui/async-await/in-trait/async-example-desugared-boxed.stderr b/tests/ui/async-await/in-trait/async-example-desugared-boxed.stderr index 54aba77cc05d0..36f90c7bcd5fe 100644 --- a/tests/ui/async-await/in-trait/async-example-desugared-boxed.stderr +++ b/tests/ui/async-await/in-trait/async-example-desugared-boxed.stderr @@ -8,11 +8,13 @@ LL | fn foo(&self) -> Pin + '_>> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: add `#[allow(refining_impl_trait)]` if it is intended for this to be part of the public API of this crate + = note: we are soliciting feedback, see issue #121718 for more information note: the lint level is defined here --> $DIR/async-example-desugared-boxed.rs:13:12 | LL | #[warn(refining_impl_trait)] | ^^^^^^^^^^^^^^^^^^^ + = note: `#[warn(refining_impl_trait_reachable)]` implied by `#[warn(refining_impl_trait)]` help: replace the return type so that it matches the trait | LL | fn foo(&self) -> impl Future { diff --git a/tests/ui/async-await/in-trait/async-example-desugared-manual.stderr b/tests/ui/async-await/in-trait/async-example-desugared-manual.stderr index d94afd92c5691..8e39559071f16 100644 --- a/tests/ui/async-await/in-trait/async-example-desugared-manual.stderr +++ b/tests/ui/async-await/in-trait/async-example-desugared-manual.stderr @@ -8,11 +8,13 @@ LL | fn foo(&self) -> MyFuture { | ^^^^^^^^ | = note: add `#[allow(refining_impl_trait)]` if it is intended for this to be part of the public API of this crate + = note: we are soliciting feedback, see issue #121718 for more information note: the lint level is defined here --> $DIR/async-example-desugared-manual.rs:21:12 | LL | #[warn(refining_impl_trait)] | ^^^^^^^^^^^^^^^^^^^ + = note: `#[warn(refining_impl_trait_reachable)]` implied by `#[warn(refining_impl_trait)]` help: replace the return type so that it matches the trait | LL | fn foo(&self) -> impl Future { diff --git a/tests/ui/attributes/validation-on-associated-items-issue-121537.rs b/tests/ui/attributes/validation-on-associated-items-issue-121537.rs new file mode 100644 index 0000000000000..60e5a21eec774 --- /dev/null +++ b/tests/ui/attributes/validation-on-associated-items-issue-121537.rs @@ -0,0 +1,7 @@ +trait MyTrait { + #[doc = MyTrait] + //~^ ERROR attribute value must be a literal + fn myfun(); +} + +fn main() {} diff --git a/tests/ui/attributes/validation-on-associated-items-issue-121537.stderr b/tests/ui/attributes/validation-on-associated-items-issue-121537.stderr new file mode 100644 index 0000000000000..9c37bb8231790 --- /dev/null +++ b/tests/ui/attributes/validation-on-associated-items-issue-121537.stderr @@ -0,0 +1,8 @@ +error: attribute value must be a literal + --> $DIR/validation-on-associated-items-issue-121537.rs:2:13 + | +LL | #[doc = MyTrait] + | ^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/delegation/duplicate-definition-inside-trait-impl.rs b/tests/ui/delegation/duplicate-definition-inside-trait-impl.rs new file mode 100644 index 0000000000000..bd685b40b2ff5 --- /dev/null +++ b/tests/ui/delegation/duplicate-definition-inside-trait-impl.rs @@ -0,0 +1,23 @@ +#![feature(fn_delegation)] +//~^ WARN the feature `fn_delegation` is incomplete + +trait Trait { + fn foo(&self) -> u32 { 0 } +} + +struct F; +struct S; + +mod to_reuse { + use crate::S; + + pub fn foo(_: &S) -> u32 { 0 } +} + +impl Trait for S { + reuse to_reuse::foo { self } + reuse Trait::foo; + //~^ ERROR duplicate definitions with name `foo` +} + +fn main() {} diff --git a/tests/ui/delegation/duplicate-definition-inside-trait-impl.stderr b/tests/ui/delegation/duplicate-definition-inside-trait-impl.stderr new file mode 100644 index 0000000000000..a5f9e6ad0bf47 --- /dev/null +++ b/tests/ui/delegation/duplicate-definition-inside-trait-impl.stderr @@ -0,0 +1,23 @@ +error[E0201]: duplicate definitions with name `foo`: + --> $DIR/duplicate-definition-inside-trait-impl.rs:19:5 + | +LL | fn foo(&self) -> u32 { 0 } + | -------------------------- item in trait +... +LL | reuse to_reuse::foo { self } + | ---------------------------- previous definition here +LL | reuse Trait::foo; + | ^^^^^^^^^^^^^^^^^ duplicate definition + +warning: the feature `fn_delegation` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/duplicate-definition-inside-trait-impl.rs:1:12 + | +LL | #![feature(fn_delegation)] + | ^^^^^^^^^^^^^ + | + = note: see issue #118212 for more information + = note: `#[warn(incomplete_features)]` on by default + +error: aborting due to 1 previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0201`. diff --git a/tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit.stderr b/tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit.stderr index c898d17f4b709..022df6f906cf4 100644 --- a/tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit.stderr +++ b/tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit.stderr @@ -22,7 +22,8 @@ LL | fn iter(&self) -> impl 'a + Iterator> { | ^^ this bound is stronger than that defined on the trait | = note: add `#[allow(refining_impl_trait)]` if it is intended for this to be part of the public API of this crate - = note: `#[warn(refining_impl_trait)]` on by default + = note: we are soliciting feedback, see issue #121718 for more information + = note: `#[warn(refining_impl_trait_reachable)]` on by default help: replace the return type so that it matches the trait | LL | fn iter(&self) -> impl Iterator::Item<'_>> + '_ { diff --git a/tests/ui/impl-trait/in-trait/foreign.rs b/tests/ui/impl-trait/in-trait/foreign.rs index e28bc9e00cbbb..ca759afc2e6ee 100644 --- a/tests/ui/impl-trait/in-trait/foreign.rs +++ b/tests/ui/impl-trait/in-trait/foreign.rs @@ -17,9 +17,29 @@ impl Foo for Local { } } -struct LocalIgnoreRefining; -impl Foo for LocalIgnoreRefining { - #[deny(refining_impl_trait)] +struct LocalOnlyRefiningA; +impl Foo for LocalOnlyRefiningA { + #[warn(refining_impl_trait)] + fn bar(self) -> Arc { + //~^ WARN impl method signature does not match trait method signature + Arc::new(String::new()) + } +} + +struct LocalOnlyRefiningB; +impl Foo for LocalOnlyRefiningB { + #[warn(refining_impl_trait)] + #[allow(refining_impl_trait_reachable)] + fn bar(self) -> Arc { + //~^ WARN impl method signature does not match trait method signature + Arc::new(String::new()) + } +} + +struct LocalOnlyRefiningC; +impl Foo for LocalOnlyRefiningC { + #[warn(refining_impl_trait)] + #[allow(refining_impl_trait_internal)] fn bar(self) -> Arc { Arc::new(String::new()) } @@ -34,5 +54,7 @@ fn main() { let &() = Foreign.bar(); let x: Arc = Local.bar(); - let x: Arc = LocalIgnoreRefining.bar(); + let x: Arc = LocalOnlyRefiningA.bar(); + let x: Arc = LocalOnlyRefiningB.bar(); + let x: Arc = LocalOnlyRefiningC.bar(); } diff --git a/tests/ui/impl-trait/in-trait/foreign.stderr b/tests/ui/impl-trait/in-trait/foreign.stderr new file mode 100644 index 0000000000000..1a5a4f2432b1e --- /dev/null +++ b/tests/ui/impl-trait/in-trait/foreign.stderr @@ -0,0 +1,39 @@ +warning: impl trait in impl method signature does not match trait method signature + --> $DIR/foreign.rs:23:21 + | +LL | fn bar(self) -> Arc { + | ^^^^^^^^^^^ + | + = note: add `#[allow(refining_impl_trait)]` if it is intended for this to be part of the public API of this crate + = note: we are soliciting feedback, see issue #121718 for more information +note: the lint level is defined here + --> $DIR/foreign.rs:22:12 + | +LL | #[warn(refining_impl_trait)] + | ^^^^^^^^^^^^^^^^^^^ + = note: `#[warn(refining_impl_trait_internal)]` implied by `#[warn(refining_impl_trait)]` +help: replace the return type so that it matches the trait + | +LL | fn bar(self) -> impl Deref { + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +warning: impl trait in impl method signature does not match trait method signature + --> $DIR/foreign.rs:33:21 + | +LL | fn bar(self) -> Arc { + | ^^^^^^^^^^^ + | + = note: add `#[allow(refining_impl_trait)]` if it is intended for this to be part of the public API of this crate + = note: we are soliciting feedback, see issue #121718 for more information +note: the lint level is defined here + --> $DIR/foreign.rs:31:12 + | +LL | #[warn(refining_impl_trait)] + | ^^^^^^^^^^^^^^^^^^^ +help: replace the return type so that it matches the trait + | +LL | fn bar(self) -> impl Deref { + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +warning: 2 warnings emitted + diff --git a/tests/ui/impl-trait/in-trait/refine.rs b/tests/ui/impl-trait/in-trait/refine.rs index 100e6da06a885..6813c3bbf2708 100644 --- a/tests/ui/impl-trait/in-trait/refine.rs +++ b/tests/ui/impl-trait/in-trait/refine.rs @@ -25,6 +25,7 @@ impl Foo for C { struct Private; impl Foo for Private { fn bar() -> () {} + //~^ ERROR impl method signature does not match trait method signature } pub trait Arg { @@ -32,6 +33,7 @@ pub trait Arg { } impl Arg for A { fn bar() -> () {} + //~^ ERROR impl method signature does not match trait method signature } pub trait Late { @@ -52,6 +54,7 @@ mod unreachable { struct E; impl UnreachablePub for E { fn bar() {} + //~^ ERROR impl method signature does not match trait method signature } } diff --git a/tests/ui/impl-trait/in-trait/refine.stderr b/tests/ui/impl-trait/in-trait/refine.stderr index 96a9bc059c842..8d30b03592166 100644 --- a/tests/ui/impl-trait/in-trait/refine.stderr +++ b/tests/ui/impl-trait/in-trait/refine.stderr @@ -8,11 +8,13 @@ LL | fn bar() -> impl Copy {} | ^^^^ this bound is stronger than that defined on the trait | = note: add `#[allow(refining_impl_trait)]` if it is intended for this to be part of the public API of this crate + = note: we are soliciting feedback, see issue #121718 for more information note: the lint level is defined here --> $DIR/refine.rs:1:9 | LL | #![deny(refining_impl_trait)] | ^^^^^^^^^^^^^^^^^^^ + = note: `#[deny(refining_impl_trait_reachable)]` implied by `#[deny(refining_impl_trait)]` help: replace the return type so that it matches the trait | LL | fn bar() -> impl Sized {} @@ -28,6 +30,7 @@ LL | fn bar() {} | ^^^^^^^^ | = note: add `#[allow(refining_impl_trait)]` if it is intended for this to be part of the public API of this crate + = note: we are soliciting feedback, see issue #121718 for more information help: replace the return type so that it matches the trait | LL | fn bar()-> impl Sized {} @@ -43,13 +46,47 @@ LL | fn bar() -> () {} | ^^ | = note: add `#[allow(refining_impl_trait)]` if it is intended for this to be part of the public API of this crate + = note: we are soliciting feedback, see issue #121718 for more information help: replace the return type so that it matches the trait | LL | fn bar() -> impl Sized {} | ~~~~~~~~~~ error: impl trait in impl method signature does not match trait method signature - --> $DIR/refine.rs:43:27 + --> $DIR/refine.rs:27:17 + | +LL | fn bar() -> impl Sized; + | ---------- return type from trait method defined here +... +LL | fn bar() -> () {} + | ^^ + | + = note: add `#[allow(refining_impl_trait)]` if it is intended for this to be part of the public API of this crate + = note: we are soliciting feedback, see issue #121718 for more information + = note: `#[deny(refining_impl_trait_internal)]` implied by `#[deny(refining_impl_trait)]` +help: replace the return type so that it matches the trait + | +LL | fn bar() -> impl Sized {} + | ~~~~~~~~~~ + +error: impl trait in impl method signature does not match trait method signature + --> $DIR/refine.rs:35:17 + | +LL | fn bar() -> impl Sized; + | ---------- return type from trait method defined here +... +LL | fn bar() -> () {} + | ^^ + | + = note: add `#[allow(refining_impl_trait)]` if it is intended for this to be part of the public API of this crate + = note: we are soliciting feedback, see issue #121718 for more information +help: replace the return type so that it matches the trait + | +LL | fn bar() -> impl Sized {} + | ~~~~~~~~~~ + +error: impl trait in impl method signature does not match trait method signature + --> $DIR/refine.rs:45:27 | LL | fn bar<'a>(&'a self) -> impl Sized + 'a; | --------------- return type from trait method defined here @@ -58,10 +95,27 @@ LL | fn bar(&self) -> impl Copy + '_ {} | ^^^^ this bound is stronger than that defined on the trait | = note: add `#[allow(refining_impl_trait)]` if it is intended for this to be part of the public API of this crate + = note: we are soliciting feedback, see issue #121718 for more information help: replace the return type so that it matches the trait | LL | fn bar(&self) -> impl Sized + '_ {} | ~~~~~~~~~~~~~~~ -error: aborting due to 4 previous errors +error: impl trait in impl method signature does not match trait method signature + --> $DIR/refine.rs:56:9 + | +LL | fn bar() -> impl Sized; + | ---------- return type from trait method defined here +... +LL | fn bar() {} + | ^^^^^^^^ + | + = note: add `#[allow(refining_impl_trait)]` if it is intended for this to be part of the public API of this crate + = note: we are soliciting feedback, see issue #121718 for more information +help: replace the return type so that it matches the trait + | +LL | fn bar()-> impl Sized {} + | +++++++++++++ + +error: aborting due to 7 previous errors diff --git a/triagebot.toml b/triagebot.toml index c972dce1a022d..89ffb2f41bb67 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -548,6 +548,10 @@ cc = ["@GuillaumeGomez"] message = "Some changes occurred in GUI tests." cc = ["@GuillaumeGomez"] +[mentions."tests/run-make/"] +message = "Some changes occurred in run-make tests." +cc = ["@jieyouxu"] + [mentions."src/librustdoc/html/static/css/themes/ayu.css"] message = "A change occurred in the Ayu theme." cc = ["@Cldfire"] @@ -571,10 +575,17 @@ cc = ["@ehuss"] [mentions."src/tools/clippy"] cc = ["@rust-lang/clippy"] +[mentions."src/tools/compiletest"] +cc = ["@jieyouxu"] + [mentions."src/tools/miri"] message = "The Miri subtree was changed" cc = ["@rust-lang/miri"] +[mentions."src/tools/run-make-support"] +message = "The run-make-support library was changed" +cc = ["@jieyouxu"] + [mentions."src/tools/rust-analyzer"] message = """ rust-analyzer is developed in its own repository. If possible, consider making \