Implements a FCW lint to detect uses of ambiguously glob imported traits.
This commit is contained in:
parent
8c52f735ab
commit
3369a17e51
9 changed files with 473 additions and 19 deletions
|
|
@ -4595,6 +4595,11 @@ pub struct Upvar {
|
|||
pub struct TraitCandidate {
|
||||
pub def_id: DefId,
|
||||
pub import_ids: SmallVec<[LocalDefId; 1]>,
|
||||
// Indicates whether this trait candidate is ambiguously glob imported
|
||||
// in it's scope. Related to the AMBIGUOUS_GLOB_IMPORTED_TRAITS lint.
|
||||
// If this is set to true and the trait is used as a result of method lookup, this
|
||||
// lint is thrown.
|
||||
pub lint_ambiguous: bool,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, HashStable_Generic)]
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
use std::fmt::Debug;
|
||||
use std::ops::Deref;
|
||||
|
||||
use rustc_hir as hir;
|
||||
|
|
@ -12,7 +13,9 @@ use rustc_hir_analysis::hir_ty_lowering::{
|
|||
use rustc_infer::infer::{
|
||||
BoundRegionConversionTime, DefineOpaqueTypes, InferOk, RegionVariableOrigin,
|
||||
};
|
||||
use rustc_lint::builtin::RESOLVING_TO_ITEMS_SHADOWING_SUPERTRAIT_ITEMS;
|
||||
use rustc_lint::builtin::{
|
||||
AMBIGUOUS_GLOB_IMPORTED_TRAITS, RESOLVING_TO_ITEMS_SHADOWING_SUPERTRAIT_ITEMS,
|
||||
};
|
||||
use rustc_middle::traits::ObligationCauseCode;
|
||||
use rustc_middle::ty::adjustment::{
|
||||
Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, PointerCoercion,
|
||||
|
|
@ -149,6 +152,9 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
|
|||
// Lint when an item is shadowing a supertrait item.
|
||||
self.lint_shadowed_supertrait_items(pick, segment);
|
||||
|
||||
// Lint when a trait is ambiguously imported
|
||||
self.lint_ambiguously_glob_imported_traits(pick, segment);
|
||||
|
||||
// Add any trait/regions obligations specified on the method's type parameters.
|
||||
// We won't add these if we encountered an illegal sized bound, so that we can use
|
||||
// a custom error in that case.
|
||||
|
|
@ -322,7 +328,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
|
|||
})
|
||||
}
|
||||
|
||||
probe::TraitPick => {
|
||||
probe::TraitPick(_) => {
|
||||
let trait_def_id = pick.item.container_id(self.tcx);
|
||||
|
||||
// Make a trait reference `$0 : Trait<$1...$n>`
|
||||
|
|
@ -716,6 +722,25 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
|
|||
);
|
||||
}
|
||||
|
||||
fn lint_ambiguously_glob_imported_traits(
|
||||
&self,
|
||||
pick: &probe::Pick<'_>,
|
||||
segment: &hir::PathSegment<'tcx>,
|
||||
) {
|
||||
if pick.kind != probe::PickKind::TraitPick(true) {
|
||||
return;
|
||||
}
|
||||
let trait_name = self.tcx.item_name(pick.item.container_id(self.tcx));
|
||||
let import_span = self.tcx.hir_span_if_local(pick.import_ids[0].to_def_id()).unwrap();
|
||||
|
||||
self.tcx.node_lint(AMBIGUOUS_GLOB_IMPORTED_TRAITS, segment.hir_id, |diag| {
|
||||
diag.primary_message(format!("Use of ambiguously glob imported trait `{trait_name}`"))
|
||||
.span(segment.ident.span)
|
||||
.span_label(import_span, format!("`{trait_name}` imported ambiguously here"))
|
||||
.help(format!("Import `{trait_name}` explicitly"));
|
||||
});
|
||||
}
|
||||
|
||||
fn upcast(
|
||||
&mut self,
|
||||
source_trait_ref: ty::PolyTraitRef<'tcx>,
|
||||
|
|
|
|||
|
|
@ -106,7 +106,7 @@ pub(crate) struct Candidate<'tcx> {
|
|||
pub(crate) enum CandidateKind<'tcx> {
|
||||
InherentImplCandidate { impl_def_id: DefId, receiver_steps: usize },
|
||||
ObjectCandidate(ty::PolyTraitRef<'tcx>),
|
||||
TraitCandidate(ty::PolyTraitRef<'tcx>),
|
||||
TraitCandidate(ty::PolyTraitRef<'tcx>, bool /* lint_ambiguous */),
|
||||
WhereClauseCandidate(ty::PolyTraitRef<'tcx>),
|
||||
}
|
||||
|
||||
|
|
@ -235,7 +235,10 @@ pub(crate) struct Pick<'tcx> {
|
|||
pub(crate) enum PickKind<'tcx> {
|
||||
InherentImplPick,
|
||||
ObjectPick,
|
||||
TraitPick,
|
||||
TraitPick(
|
||||
// Is Ambiguously Imported
|
||||
bool,
|
||||
),
|
||||
WhereClausePick(
|
||||
// Trait
|
||||
ty::PolyTraitRef<'tcx>,
|
||||
|
|
@ -560,7 +563,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
probe_cx.push_candidate(
|
||||
Candidate {
|
||||
item,
|
||||
kind: CandidateKind::TraitCandidate(ty::Binder::dummy(trait_ref)),
|
||||
kind: CandidateKind::TraitCandidate(
|
||||
ty::Binder::dummy(trait_ref),
|
||||
false,
|
||||
),
|
||||
import_ids: smallvec![],
|
||||
},
|
||||
false,
|
||||
|
|
@ -1018,6 +1024,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||
self.assemble_extension_candidates_for_trait(
|
||||
&trait_candidate.import_ids,
|
||||
trait_did,
|
||||
trait_candidate.lint_ambiguous,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -1029,7 +1036,11 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||
let mut duplicates = FxHashSet::default();
|
||||
for trait_info in suggest::all_traits(self.tcx) {
|
||||
if duplicates.insert(trait_info.def_id) {
|
||||
self.assemble_extension_candidates_for_trait(&smallvec![], trait_info.def_id);
|
||||
self.assemble_extension_candidates_for_trait(
|
||||
&smallvec![],
|
||||
trait_info.def_id,
|
||||
false,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1055,6 +1066,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||
&mut self,
|
||||
import_ids: &SmallVec<[LocalDefId; 1]>,
|
||||
trait_def_id: DefId,
|
||||
lint_ambiguous: bool,
|
||||
) {
|
||||
let trait_args = self.fresh_args_for_item(self.span, trait_def_id);
|
||||
let trait_ref = ty::TraitRef::new_from_args(self.tcx, trait_def_id, trait_args);
|
||||
|
|
@ -1076,7 +1088,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||
Candidate {
|
||||
item,
|
||||
import_ids: import_ids.clone(),
|
||||
kind: TraitCandidate(bound_trait_ref),
|
||||
kind: TraitCandidate(bound_trait_ref, lint_ambiguous),
|
||||
},
|
||||
false,
|
||||
);
|
||||
|
|
@ -1099,7 +1111,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||
Candidate {
|
||||
item,
|
||||
import_ids: import_ids.clone(),
|
||||
kind: TraitCandidate(ty::Binder::dummy(trait_ref)),
|
||||
kind: TraitCandidate(ty::Binder::dummy(trait_ref), lint_ambiguous),
|
||||
},
|
||||
false,
|
||||
);
|
||||
|
|
@ -1842,7 +1854,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||
ObjectCandidate(_) | WhereClauseCandidate(_) => {
|
||||
CandidateSource::Trait(candidate.item.container_id(self.tcx))
|
||||
}
|
||||
TraitCandidate(trait_ref) => self.probe(|_| {
|
||||
TraitCandidate(trait_ref, _) => self.probe(|_| {
|
||||
let trait_ref = self.instantiate_binder_with_fresh_vars(
|
||||
self.span,
|
||||
BoundRegionConversionTime::FnCall,
|
||||
|
|
@ -1872,7 +1884,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||
fn candidate_source_from_pick(&self, pick: &Pick<'tcx>) -> CandidateSource {
|
||||
match pick.kind {
|
||||
InherentImplPick => CandidateSource::Impl(pick.item.container_id(self.tcx)),
|
||||
ObjectPick | WhereClausePick(_) | TraitPick => {
|
||||
ObjectPick | WhereClausePick(_) | TraitPick(_) => {
|
||||
CandidateSource::Trait(pick.item.container_id(self.tcx))
|
||||
}
|
||||
}
|
||||
|
|
@ -1948,7 +1960,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||
impl_bounds,
|
||||
));
|
||||
}
|
||||
TraitCandidate(poly_trait_ref) => {
|
||||
TraitCandidate(poly_trait_ref, _) => {
|
||||
// Some trait methods are excluded for arrays before 2021.
|
||||
// (`array.into_iter()` wants a slice iterator for compatibility.)
|
||||
if let Some(method_name) = self.method_name {
|
||||
|
|
@ -2274,11 +2286,16 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
let lint_ambiguous = match probes[0].0.kind {
|
||||
TraitCandidate(_, lint) => lint,
|
||||
_ => false,
|
||||
};
|
||||
|
||||
// FIXME: check the return type here somehow.
|
||||
// If so, just use this trait and call it a day.
|
||||
Some(Pick {
|
||||
item: probes[0].0.item,
|
||||
kind: TraitPick,
|
||||
kind: TraitPick(lint_ambiguous),
|
||||
import_ids: probes[0].0.import_ids.clone(),
|
||||
autoderefs: 0,
|
||||
autoref_or_ptr_adjustment: None,
|
||||
|
|
@ -2348,9 +2365,14 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
let lint_ambiguous = match probes[0].0.kind {
|
||||
TraitCandidate(_, lint) => lint,
|
||||
_ => false,
|
||||
};
|
||||
|
||||
Some(Pick {
|
||||
item: child_candidate.item,
|
||||
kind: TraitPick,
|
||||
kind: TraitPick(lint_ambiguous),
|
||||
import_ids: child_candidate.import_ids.clone(),
|
||||
autoderefs: 0,
|
||||
autoref_or_ptr_adjustment: None,
|
||||
|
|
@ -2613,7 +2635,7 @@ impl<'tcx> Candidate<'tcx> {
|
|||
kind: match self.kind {
|
||||
InherentImplCandidate { .. } => InherentImplPick,
|
||||
ObjectCandidate(_) => ObjectPick,
|
||||
TraitCandidate(_) => TraitPick,
|
||||
TraitCandidate(_, lint_ambiguous) => TraitPick(lint_ambiguous),
|
||||
WhereClauseCandidate(trait_ref) => {
|
||||
// Only trait derived from where-clauses should
|
||||
// appear here, so they should not contain any
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ declare_lint_pass! {
|
|||
AARCH64_SOFTFLOAT_NEON,
|
||||
ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE,
|
||||
AMBIGUOUS_ASSOCIATED_ITEMS,
|
||||
AMBIGUOUS_GLOB_IMPORTED_TRAITS,
|
||||
AMBIGUOUS_GLOB_IMPORTS,
|
||||
AMBIGUOUS_GLOB_REEXPORTS,
|
||||
AMBIGUOUS_PANIC_IMPORTS,
|
||||
|
|
@ -4473,6 +4474,60 @@ declare_lint! {
|
|||
};
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
/// The `ambiguous_glob_imported_traits` lint reports uses of traits that are
|
||||
/// imported ambiguously via glob imports. Previously, this was not enforced
|
||||
/// due to a bug in rustc.
|
||||
///
|
||||
/// ### Example
|
||||
///
|
||||
/// ```rust,compile_fail
|
||||
/// #![deny(ambiguous_glob_imported_traits)]
|
||||
/// mod m1 {
|
||||
/// pub trait Trait {
|
||||
/// fn method1(&self) {}
|
||||
/// }
|
||||
/// impl Trait for u8 {}
|
||||
/// }
|
||||
/// mod m2 {
|
||||
/// pub trait Trait {
|
||||
/// fn method2(&self) {}
|
||||
/// }
|
||||
/// impl Trait for u8 {}
|
||||
/// }
|
||||
///
|
||||
/// fn main() {
|
||||
/// use m1::*;
|
||||
/// use m2::*;
|
||||
/// 0u8.method1();
|
||||
/// 0u8.method2();
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// {{produces}}
|
||||
///
|
||||
/// ### Explanation
|
||||
///
|
||||
/// When multiple traits with the same name are brought into scope through glob imports,
|
||||
/// one trait becomes the "primary" one while the others are shadowed. Methods from the
|
||||
/// shadowed traits (e.g. `method2`) become inaccessible, while methods from the "primary"
|
||||
/// trait (e.g. `method1`) still resolve. Ideally, none of the ambiguous traits would be in scope,
|
||||
/// but we have to allow this for now because of backwards compatibility.
|
||||
/// This lint reports uses of these "primary" traits that are ambiguous.
|
||||
///
|
||||
/// This is a [future-incompatible] lint to transition this to a
|
||||
/// hard error in the future.
|
||||
///
|
||||
/// [future-incompatible]: ../index.md#future-incompatible-lints
|
||||
pub AMBIGUOUS_GLOB_IMPORTED_TRAITS,
|
||||
Warn,
|
||||
"detects uses of ambiguously glob imported traits",
|
||||
@future_incompatible = FutureIncompatibleInfo {
|
||||
reason: fcw!(FutureReleaseError #147992),
|
||||
report_in_deps: false,
|
||||
};
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
/// The `ambiguous_panic_imports` lint detects ambiguous core and std panic imports, but
|
||||
/// previously didn't do that due to `#[macro_use]` prelude macro import.
|
||||
|
|
|
|||
|
|
@ -622,7 +622,18 @@ struct ModuleData<'ra> {
|
|||
globs: CmRefCell<Vec<Import<'ra>>>,
|
||||
|
||||
/// Used to memoize the traits in this module for faster searches through all traits in scope.
|
||||
traits: CmRefCell<Option<Box<[(Macros20NormalizedIdent, Decl<'ra>, Option<Module<'ra>>)]>>>,
|
||||
traits: CmRefCell<
|
||||
Option<
|
||||
Box<
|
||||
[(
|
||||
Macros20NormalizedIdent,
|
||||
Decl<'ra>,
|
||||
Option<Module<'ra>>,
|
||||
bool, /* lint ambiguous */
|
||||
)],
|
||||
>,
|
||||
>,
|
||||
>,
|
||||
|
||||
/// Span of the module itself. Used for error reporting.
|
||||
span: Span,
|
||||
|
|
@ -719,7 +730,12 @@ impl<'ra> Module<'ra> {
|
|||
return;
|
||||
}
|
||||
if let Res::Def(DefKind::Trait | DefKind::TraitAlias, def_id) = binding.res() {
|
||||
collected_traits.push((name, binding, r.as_ref().get_module(def_id)))
|
||||
collected_traits.push((
|
||||
name,
|
||||
binding,
|
||||
r.as_ref().get_module(def_id),
|
||||
binding.is_ambiguity_recursive(),
|
||||
));
|
||||
}
|
||||
});
|
||||
*traits = Some(collected_traits.into_boxed_slice());
|
||||
|
|
@ -1925,7 +1941,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
if let Some(module) = current_trait {
|
||||
if self.trait_may_have_item(Some(module), assoc_item) {
|
||||
let def_id = module.def_id();
|
||||
found_traits.push(TraitCandidate { def_id, import_ids: smallvec![] });
|
||||
found_traits.push(TraitCandidate {
|
||||
def_id,
|
||||
import_ids: smallvec![],
|
||||
lint_ambiguous: false,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1963,11 +1983,13 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
) {
|
||||
module.ensure_traits(self);
|
||||
let traits = module.traits.borrow();
|
||||
for &(trait_name, trait_binding, trait_module) in traits.as_ref().unwrap().iter() {
|
||||
for &(trait_name, trait_binding, trait_module, lint_ambiguous) in
|
||||
traits.as_ref().unwrap().iter()
|
||||
{
|
||||
if self.trait_may_have_item(trait_module, assoc_item) {
|
||||
let def_id = trait_binding.res().def_id();
|
||||
let import_ids = self.find_transitive_imports(&trait_binding.kind, trait_name.0);
|
||||
found_traits.push(TraitCandidate { def_id, import_ids });
|
||||
found_traits.push(TraitCandidate { def_id, import_ids, lint_ambiguous });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
84
tests/ui/imports/ambiguous-trait-in-scope.rs
Normal file
84
tests/ui/imports/ambiguous-trait-in-scope.rs
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
//@ edition:2018
|
||||
//@ aux-crate:external=ambiguous-trait-reexport.rs
|
||||
|
||||
mod m1 {
|
||||
pub trait Trait {
|
||||
fn method1(&self) {}
|
||||
}
|
||||
impl Trait for u8 {}
|
||||
}
|
||||
mod m2 {
|
||||
pub trait Trait {
|
||||
fn method2(&self) {}
|
||||
}
|
||||
impl Trait for u8 {}
|
||||
}
|
||||
mod m1_reexport {
|
||||
pub use crate::m1::Trait;
|
||||
}
|
||||
mod m2_reexport {
|
||||
pub use crate::m2::Trait;
|
||||
}
|
||||
|
||||
mod ambig_reexport {
|
||||
pub use crate::m1::*;
|
||||
pub use crate::m2::*;
|
||||
}
|
||||
|
||||
fn test1() {
|
||||
// Create an ambiguous import for `Trait` in one order
|
||||
use m1::*;
|
||||
use m2::*;
|
||||
0u8.method1(); //~ WARNING Use of ambiguously glob imported trait `Trait` [ambiguous_glob_imported_traits]
|
||||
//~| WARNING this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
0u8.method2(); //~ ERROR: no method named `method2` found for type `u8` in the current scope
|
||||
}
|
||||
|
||||
fn test2() {
|
||||
// Create an ambiguous import for `Trait` in another order
|
||||
use m2::*;
|
||||
use m1::*;
|
||||
0u8.method1(); //~ ERROR: no method named `method1` found for type `u8` in the current scope
|
||||
0u8.method2(); //~ WARNING Use of ambiguously glob imported trait `Trait` [ambiguous_glob_imported_traits]
|
||||
//~| WARNING this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
}
|
||||
|
||||
fn test_indirect_reexport() {
|
||||
use m1_reexport::*;
|
||||
use m2_reexport::*;
|
||||
0u8.method1(); //~ WARNING Use of ambiguously glob imported trait `Trait` [ambiguous_glob_imported_traits]
|
||||
//~| WARNING this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
0u8.method2(); //~ ERROR: no method named `method2` found for type `u8` in the current scope
|
||||
}
|
||||
|
||||
fn test_ambig_reexport() {
|
||||
use ambig_reexport::*;
|
||||
0u8.method1(); //~ WARNING Use of ambiguously glob imported trait `Trait` [ambiguous_glob_imported_traits]
|
||||
//~| WARNING this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
0u8.method2(); //~ ERROR: no method named `method2` found for type `u8` in the current scope
|
||||
}
|
||||
|
||||
fn test_external() {
|
||||
use external::m1::*;
|
||||
use external::m2::*;
|
||||
0u8.method1(); //~ WARNING Use of ambiguously glob imported trait `Trait` [ambiguous_glob_imported_traits]
|
||||
//~| WARNING this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
0u8.method2(); //~ ERROR: no method named `method2` found for type `u8` in the current scope
|
||||
}
|
||||
|
||||
fn test_external_indirect_reexport() {
|
||||
use external::m1_reexport::*;
|
||||
use external::m2_reexport::*;
|
||||
0u8.method1(); //~ WARNING Use of ambiguously glob imported trait `Trait` [ambiguous_glob_imported_traits]
|
||||
//~| WARNING this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
0u8.method2(); //~ ERROR: no method named `method2` found for type `u8` in the current scope
|
||||
}
|
||||
|
||||
fn test_external_ambig_reexport() {
|
||||
use external::ambig_reexport::*;
|
||||
0u8.method1(); //~ WARNING Use of ambiguously glob imported trait `Trait` [ambiguous_glob_imported_traits]
|
||||
//~| WARNING this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
0u8.method2(); //~ ERROR: no method named `method2` found for type `u8` in the current scope
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
191
tests/ui/imports/ambiguous-trait-in-scope.stderr
Normal file
191
tests/ui/imports/ambiguous-trait-in-scope.stderr
Normal file
|
|
@ -0,0 +1,191 @@
|
|||
warning: Use of ambiguously glob imported trait `Trait`
|
||||
--> $DIR/ambiguous-trait-in-scope.rs:32:9
|
||||
|
|
||||
LL | use m1::*;
|
||||
| -- `Trait` imported ambiguously here
|
||||
LL | use m2::*;
|
||||
LL | 0u8.method1();
|
||||
| ^^^^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #147992 <https://github.com/rust-lang/rust/issues/147992>
|
||||
= help: Import `Trait` explicitly
|
||||
= note: `#[warn(ambiguous_glob_imported_traits)]` (part of `#[warn(future_incompatible)]`) on by default
|
||||
|
||||
error[E0599]: no method named `method2` found for type `u8` in the current scope
|
||||
--> $DIR/ambiguous-trait-in-scope.rs:34:9
|
||||
|
|
||||
LL | 0u8.method2();
|
||||
| ^^^^^^^ method not found in `u8`
|
||||
|
|
||||
= help: items from traits can only be used if the trait is in scope
|
||||
help: the following traits which provide `method2` are implemented but not in scope; perhaps you want to import one of them
|
||||
|
|
||||
LL + use ambiguous_trait_reexport::m2::Trait;
|
||||
|
|
||||
LL + use crate::m2::Trait;
|
||||
|
|
||||
|
||||
error[E0599]: no method named `method1` found for type `u8` in the current scope
|
||||
--> $DIR/ambiguous-trait-in-scope.rs:41:9
|
||||
|
|
||||
LL | 0u8.method1();
|
||||
| ^^^^^^^ method not found in `u8`
|
||||
|
|
||||
= help: items from traits can only be used if the trait is in scope
|
||||
help: the following traits which provide `method1` are implemented but not in scope; perhaps you want to import one of them
|
||||
|
|
||||
LL + use ambiguous_trait_reexport::m1::Trait;
|
||||
|
|
||||
LL + use crate::m1::Trait;
|
||||
|
|
||||
|
||||
warning: Use of ambiguously glob imported trait `Trait`
|
||||
--> $DIR/ambiguous-trait-in-scope.rs:42:9
|
||||
|
|
||||
LL | use m2::*;
|
||||
| -- `Trait` imported ambiguously here
|
||||
...
|
||||
LL | 0u8.method2();
|
||||
| ^^^^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #147992 <https://github.com/rust-lang/rust/issues/147992>
|
||||
= help: Import `Trait` explicitly
|
||||
|
||||
warning: Use of ambiguously glob imported trait `Trait`
|
||||
--> $DIR/ambiguous-trait-in-scope.rs:49:9
|
||||
|
|
||||
LL | use m1_reexport::*;
|
||||
| ----------- `Trait` imported ambiguously here
|
||||
LL | use m2_reexport::*;
|
||||
LL | 0u8.method1();
|
||||
| ^^^^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #147992 <https://github.com/rust-lang/rust/issues/147992>
|
||||
= help: Import `Trait` explicitly
|
||||
|
||||
error[E0599]: no method named `method2` found for type `u8` in the current scope
|
||||
--> $DIR/ambiguous-trait-in-scope.rs:51:9
|
||||
|
|
||||
LL | 0u8.method2();
|
||||
| ^^^^^^^ method not found in `u8`
|
||||
|
|
||||
= help: items from traits can only be used if the trait is in scope
|
||||
help: the following traits which provide `method2` are implemented but not in scope; perhaps you want to import one of them
|
||||
|
|
||||
LL + use ambiguous_trait_reexport::m2::Trait;
|
||||
|
|
||||
LL + use crate::m2::Trait;
|
||||
|
|
||||
|
||||
warning: Use of ambiguously glob imported trait `Trait`
|
||||
--> $DIR/ambiguous-trait-in-scope.rs:56:9
|
||||
|
|
||||
LL | use ambig_reexport::*;
|
||||
| -------------- `Trait` imported ambiguously here
|
||||
LL | 0u8.method1();
|
||||
| ^^^^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #147992 <https://github.com/rust-lang/rust/issues/147992>
|
||||
= help: Import `Trait` explicitly
|
||||
|
||||
error[E0599]: no method named `method2` found for type `u8` in the current scope
|
||||
--> $DIR/ambiguous-trait-in-scope.rs:58:9
|
||||
|
|
||||
LL | 0u8.method2();
|
||||
| ^^^^^^^ method not found in `u8`
|
||||
|
|
||||
= help: items from traits can only be used if the trait is in scope
|
||||
help: the following traits which provide `method2` are implemented but not in scope; perhaps you want to import one of them
|
||||
|
|
||||
LL + use ambiguous_trait_reexport::m2::Trait;
|
||||
|
|
||||
LL + use crate::m2::Trait;
|
||||
|
|
||||
|
||||
warning: Use of ambiguously glob imported trait `Trait`
|
||||
--> $DIR/ambiguous-trait-in-scope.rs:64:9
|
||||
|
|
||||
LL | use external::m1::*;
|
||||
| ------------ `Trait` imported ambiguously here
|
||||
LL | use external::m2::*;
|
||||
LL | 0u8.method1();
|
||||
| ^^^^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #147992 <https://github.com/rust-lang/rust/issues/147992>
|
||||
= help: Import `Trait` explicitly
|
||||
|
||||
error[E0599]: no method named `method2` found for type `u8` in the current scope
|
||||
--> $DIR/ambiguous-trait-in-scope.rs:66:9
|
||||
|
|
||||
LL | 0u8.method2();
|
||||
| ^^^^^^^ method not found in `u8`
|
||||
|
|
||||
= help: items from traits can only be used if the trait is in scope
|
||||
help: the following traits which provide `method2` are implemented but not in scope; perhaps you want to import one of them
|
||||
|
|
||||
LL + use ambiguous_trait_reexport::m2::Trait;
|
||||
|
|
||||
LL + use crate::m2::Trait;
|
||||
|
|
||||
|
||||
warning: Use of ambiguously glob imported trait `Trait`
|
||||
--> $DIR/ambiguous-trait-in-scope.rs:72:9
|
||||
|
|
||||
LL | use external::m1_reexport::*;
|
||||
| --------------------- `Trait` imported ambiguously here
|
||||
LL | use external::m2_reexport::*;
|
||||
LL | 0u8.method1();
|
||||
| ^^^^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #147992 <https://github.com/rust-lang/rust/issues/147992>
|
||||
= help: Import `Trait` explicitly
|
||||
|
||||
error[E0599]: no method named `method2` found for type `u8` in the current scope
|
||||
--> $DIR/ambiguous-trait-in-scope.rs:74:9
|
||||
|
|
||||
LL | 0u8.method2();
|
||||
| ^^^^^^^ method not found in `u8`
|
||||
|
|
||||
= help: items from traits can only be used if the trait is in scope
|
||||
help: the following traits which provide `method2` are implemented but not in scope; perhaps you want to import one of them
|
||||
|
|
||||
LL + use ambiguous_trait_reexport::m2::Trait;
|
||||
|
|
||||
LL + use crate::m2::Trait;
|
||||
|
|
||||
|
||||
warning: Use of ambiguously glob imported trait `Trait`
|
||||
--> $DIR/ambiguous-trait-in-scope.rs:79:9
|
||||
|
|
||||
LL | use external::ambig_reexport::*;
|
||||
| ------------------------ `Trait` imported ambiguously here
|
||||
LL | 0u8.method1();
|
||||
| ^^^^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #147992 <https://github.com/rust-lang/rust/issues/147992>
|
||||
= help: Import `Trait` explicitly
|
||||
|
||||
error[E0599]: no method named `method2` found for type `u8` in the current scope
|
||||
--> $DIR/ambiguous-trait-in-scope.rs:81:9
|
||||
|
|
||||
LL | 0u8.method2();
|
||||
| ^^^^^^^ method not found in `u8`
|
||||
|
|
||||
= help: items from traits can only be used if the trait is in scope
|
||||
help: the following traits which provide `method2` are implemented but not in scope; perhaps you want to import one of them
|
||||
|
|
||||
LL + use ambiguous_trait_reexport::m2::Trait;
|
||||
|
|
||||
LL + use crate::m2::Trait;
|
||||
|
|
||||
|
||||
error: aborting due to 7 previous errors; 7 warnings emitted
|
||||
|
||||
For more information about this error, try `rustc --explain E0599`.
|
||||
23
tests/ui/imports/auxiliary/ambiguous-trait-reexport.rs
Normal file
23
tests/ui/imports/auxiliary/ambiguous-trait-reexport.rs
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
pub mod m1 {
|
||||
pub trait Trait {
|
||||
fn method1(&self) {}
|
||||
}
|
||||
impl Trait for u8 {}
|
||||
}
|
||||
pub mod m2 {
|
||||
pub trait Trait {
|
||||
fn method2(&self) {}
|
||||
}
|
||||
impl Trait for u8 {}
|
||||
}
|
||||
pub mod m1_reexport {
|
||||
pub use crate::m1::Trait;
|
||||
}
|
||||
pub mod m2_reexport {
|
||||
pub use crate::m2::Trait;
|
||||
}
|
||||
|
||||
pub mod ambig_reexport {
|
||||
pub use crate::m1::*;
|
||||
pub use crate::m2::*;
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
//@ check-pass
|
||||
// The AMBIGUOUS_GLOB_IMPORTED_TRAITS lint is reported on uses of traits that are
|
||||
// ambiguously glob imported. This test checks that we don't report this lint
|
||||
// when the same trait is glob imported multiple times.
|
||||
|
||||
mod t {
|
||||
pub trait Trait {
|
||||
fn method(&self) {}
|
||||
}
|
||||
|
||||
impl Trait for i8 {}
|
||||
}
|
||||
|
||||
mod m1 {
|
||||
pub use t::Trait;
|
||||
}
|
||||
|
||||
mod m2 {
|
||||
pub use t::Trait;
|
||||
}
|
||||
|
||||
use m1::*;
|
||||
use m2::*;
|
||||
|
||||
fn main() {
|
||||
0i8.method();
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue