Skip to content

Report missing cases of bare_trait_objects #82868

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Merged
merged 3 commits into from
Mar 18, 2021
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion compiler/rustc_ast/src/ast.rs
Original file line number Diff line number Diff line change
@@ -1964,7 +1964,7 @@ impl TyKind {
}

/// Syntax used to declare a trait object.
#[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug)]
#[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
pub enum TraitObjectSyntax {
Dyn,
None,
3 changes: 2 additions & 1 deletion compiler/rustc_ast_lowering/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1396,7 +1396,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
if kind != TraitObjectSyntax::Dyn {
self.maybe_lint_bare_trait(t.span, t.id, false);
}
hir::TyKind::TraitObject(bounds, lifetime_bound)
hir::TyKind::TraitObject(bounds, lifetime_bound, kind)
}
TyKind::ImplTrait(def_node_id, ref bounds) => {
let span = t.span;
@@ -2648,6 +2648,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
hir::TyKind::TraitObject(
arena_vec![self; principal],
self.elided_dyn_bound(span),
TraitObjectSyntax::None,
)
}
_ => hir::TyKind::Path(hir::QPath::Resolved(None, path)),
4 changes: 2 additions & 2 deletions compiler/rustc_hir/src/hir.rs
Original file line number Diff line number Diff line change
@@ -6,7 +6,7 @@ use crate::{itemlikevisit, LangItem};

use rustc_ast::util::parser::ExprPrecedence;
use rustc_ast::{self as ast, CrateSugar, LlvmAsmDialect};
use rustc_ast::{Attribute, FloatTy, IntTy, Label, LitKind, StrStyle, UintTy};
use rustc_ast::{Attribute, FloatTy, IntTy, Label, LitKind, StrStyle, TraitObjectSyntax, UintTy};
pub use rustc_ast::{BorrowKind, ImplPolarity, IsAuto};
pub use rustc_ast::{CaptureBy, Movability, Mutability};
use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
@@ -2327,7 +2327,7 @@ pub enum TyKind<'hir> {
OpaqueDef(ItemId, &'hir [GenericArg<'hir>]),
/// A trait object type `Bound1 + Bound2 + Bound3`
/// where `Bound` is a trait or a lifetime.
TraitObject(&'hir [PolyTraitRef<'hir>], Lifetime),
TraitObject(&'hir [PolyTraitRef<'hir>], Lifetime, TraitObjectSyntax),
/// Unused for now.
Typeof(AnonConst),
/// `TyKind::Infer` means the type should be inferred instead of it having been
2 changes: 1 addition & 1 deletion compiler/rustc_hir/src/intravisit.rs
Original file line number Diff line number Diff line change
@@ -709,7 +709,7 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) {
visitor.visit_ty(ty);
visitor.visit_anon_const(length)
}
TyKind::TraitObject(bounds, ref lifetime) => {
TyKind::TraitObject(bounds, ref lifetime, _syntax) => {
for bound in bounds {
visitor.visit_poly_trait_ref(bound, TraitBoundModifier::None);
}
5 changes: 4 additions & 1 deletion compiler/rustc_hir_pretty/src/lib.rs
Original file line number Diff line number Diff line change
@@ -410,7 +410,10 @@ impl<'a> State<'a> {
}
hir::TyKind::OpaqueDef(..) => self.s.word("/*impl Trait*/"),
hir::TyKind::Path(ref qpath) => self.print_qpath(qpath, false),
hir::TyKind::TraitObject(bounds, ref lifetime) => {
hir::TyKind::TraitObject(bounds, ref lifetime, syntax) => {
if syntax == ast::TraitObjectSyntax::Dyn {
self.word_space("dyn");
}
let mut first = true;
for bound in bounds {
if first {
Original file line number Diff line number Diff line change
@@ -99,7 +99,7 @@ impl Visitor<'tcx> for FindNestedTypeVisitor<'tcx> {
return;
}

hir::TyKind::TraitObject(bounds, _) => {
hir::TyKind::TraitObject(bounds, ..) => {
for bound in bounds {
self.current_index.shift_in(1);
self.visit_poly_trait_ref(bound, hir::TraitBoundModifier::None);
Original file line number Diff line number Diff line change
@@ -292,7 +292,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
);
}
}
TyKind::TraitObject(_, lt) => match lt.name {
TyKind::TraitObject(_, lt, _) => match lt.name {
LifetimeName::ImplicitObjectLifetimeDefault => {
err.span_suggestion_verbose(
fn_return.span.shrink_to_hi(),
@@ -498,6 +498,7 @@ impl<'tcx> Visitor<'tcx> for HirTraitObjectVisitor {
if let TyKind::TraitObject(
poly_trait_refs,
Lifetime { name: LifetimeName::ImplicitObjectLifetimeDefault, .. },
_,
) = t.kind
{
for ptr in poly_trait_refs {
1 change: 1 addition & 0 deletions compiler/rustc_middle/src/ty/diagnostics.rs
Original file line number Diff line number Diff line change
@@ -314,6 +314,7 @@ impl<'v> hir::intravisit::Visitor<'v> for TraitObjectVisitor<'v> {
hir::LifetimeName::ImplicitObjectLifetimeDefault | hir::LifetimeName::Static,
..
},
_,
) => {
self.0.push(ty);
}
4 changes: 2 additions & 2 deletions compiler/rustc_resolve/src/late/lifetimes.rs
Original file line number Diff line number Diff line change
@@ -540,7 +540,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
self.missing_named_lifetime_spots.pop();
self.is_in_fn_syntax = was_in_fn_syntax;
}
hir::TyKind::TraitObject(bounds, ref lifetime) => {
hir::TyKind::TraitObject(bounds, ref lifetime, _) => {
debug!("visit_ty: TraitObject(bounds={:?}, lifetime={:?})", bounds, lifetime);
for bound in bounds {
self.visit_poly_trait_ref(bound, hir::TraitBoundModifier::None);
@@ -2299,7 +2299,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
self.outer_index.shift_in(1);
}
match ty.kind {
hir::TyKind::TraitObject(bounds, ref lifetime) => {
hir::TyKind::TraitObject(bounds, ref lifetime, _) => {
for bound in bounds {
self.visit_poly_trait_ref(bound, hir::TraitBoundModifier::None);
}
2 changes: 1 addition & 1 deletion compiler/rustc_trait_selection/src/infer.rs
Original file line number Diff line number Diff line change
@@ -124,7 +124,7 @@ impl<'tcx> InferCtxtBuilderExt<'tcx> for InferCtxtBuilder<'tcx> {
DUMMY_SP,
canonical_key,
|ref infcx, key, canonical_inference_vars| {
let mut fulfill_cx = TraitEngine::new(infcx.tcx);
let mut fulfill_cx = <dyn TraitEngine<'_>>::new(infcx.tcx);
let value = operation(infcx, &mut *fulfill_cx, key)?;
infcx.make_canonicalized_query_response(
canonical_inference_vars,
Original file line number Diff line number Diff line change
@@ -62,7 +62,7 @@ fn scrape_region_constraints<'tcx, R>(
infcx: &InferCtxt<'_, 'tcx>,
op: impl FnOnce() -> Fallible<InferOk<'tcx, R>>,
) -> Fallible<(R, Option<Rc<QueryRegionConstraints<'tcx>>>)> {
let mut fulfill_cx = TraitEngine::new(infcx.tcx);
let mut fulfill_cx = <dyn TraitEngine<'_>>::new(infcx.tcx);
let dummy_body_id = ObligationCause::dummy().body_id;

// During NLL, we expect that nobody will register region
2 changes: 1 addition & 1 deletion compiler/rustc_traits/src/dropck_outlives.rs
Original file line number Diff line number Diff line change
@@ -75,7 +75,7 @@ fn dropck_outlives<'tcx>(
// Set used to detect infinite recursion.
let mut ty_set = FxHashSet::default();

let mut fulfill_cx = TraitEngine::new(infcx.tcx);
let mut fulfill_cx = <dyn TraitEngine<'_>>::new(infcx.tcx);

let cause = ObligationCause::dummy();
let mut constraints = DtorckConstraint::empty();
4 changes: 3 additions & 1 deletion compiler/rustc_typeck/src/astconv/mod.rs
Original file line number Diff line number Diff line change
@@ -1608,6 +1608,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
// the whole path.
// Will fail except for `T::A` and `Self::A`; i.e., if `qself_ty`/`qself_def` are not a type
// parameter or `Self`.
// NOTE: When this function starts resolving `Trait::AssocTy` successfully
// it should also start reportint the `BARE_TRAIT_OBJECTS` lint.
pub fn associated_path_to_ty(
&self,
hir_ref_id: hir::HirId,
@@ -2201,7 +2203,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
Some(ast_ty),
))
}
hir::TyKind::TraitObject(ref bounds, ref lifetime) => {
hir::TyKind::TraitObject(ref bounds, ref lifetime, _) => {
self.conv_object_ty_poly_trait_ref(ast_ty.span, bounds, lifetime, borrowed)
}
hir::TyKind::Path(hir::QPath::Resolved(ref maybe_qself, ref path)) => {
4 changes: 2 additions & 2 deletions compiler/rustc_typeck/src/check/coercion.rs
Original file line number Diff line number Diff line change
@@ -1554,7 +1554,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
if let hir::FnRetTy::Return(ty) = fn_output {
// Get the return type.
if let hir::TyKind::OpaqueDef(..) = ty.kind {
let ty = AstConv::ast_ty_to_ty(fcx, ty);
let ty = <dyn AstConv<'_>>::ast_ty_to_ty(fcx, ty);
// Get the `impl Trait`'s `DefId`.
if let ty::Opaque(def_id, _) = ty.kind() {
let hir_id = fcx.tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
@@ -1616,7 +1616,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
fn is_return_ty_unsized(&self, fcx: &FnCtxt<'a, 'tcx>, blk_id: hir::HirId) -> bool {
if let Some((fn_decl, _)) = fcx.get_fn_decl(blk_id) {
if let hir::FnRetTy::Return(ty) = fn_decl.output {
let ty = AstConv::ast_ty_to_ty(fcx, ty);
let ty = <dyn AstConv<'_>>::ast_ty_to_ty(fcx, ty);
if let ty::Dynamic(..) = ty.kind() {
return true;
}
2 changes: 1 addition & 1 deletion compiler/rustc_typeck/src/check/dropck.rs
Original file line number Diff line number Diff line change
@@ -77,7 +77,7 @@ fn ensure_drop_params_and_item_params_correspond<'tcx>(
tcx.infer_ctxt().enter(|ref infcx| {
let impl_param_env = tcx.param_env(self_type_did);
let tcx = infcx.tcx;
let mut fulfillment_cx = TraitEngine::new(tcx);
let mut fulfillment_cx = <dyn TraitEngine<'_>>::new(tcx);

let named_type = tcx.type_of(self_type_did);

52 changes: 41 additions & 11 deletions compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
Original file line number Diff line number Diff line change
@@ -6,14 +6,15 @@ use crate::check::callee::{self, DeferredCallResolution};
use crate::check::method::{self, MethodCallee, SelfSource};
use crate::check::{BreakableCtxt, Diverges, Expectation, FallbackMode, FnCtxt, LocalTy};

use rustc_ast::TraitObjectSyntax;
use rustc_data_structures::captures::Captures;
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::{Applicability, DiagnosticBuilder, ErrorReported};
use rustc_hir as hir;
use rustc_hir::def::{CtorOf, DefKind, Res};
use rustc_hir::def_id::DefId;
use rustc_hir::lang_items::LangItem;
use rustc_hir::{ExprKind, GenericArg, Node, QPath};
use rustc_hir::{ExprKind, GenericArg, Node, QPath, TyKind};
use rustc_infer::infer::canonical::{Canonical, OriginalQueryValues, QueryResponse};
use rustc_infer::infer::error_reporting::TypeAnnotationNeeded::E0282;
use rustc_infer::infer::{InferOk, InferResult};
@@ -26,7 +27,9 @@ use rustc_middle::ty::{
self, AdtKind, CanonicalUserType, DefIdTree, GenericParamDefKind, ToPolyTraitRef, ToPredicate,
Ty, UserType,
};
use rustc_session::{lint, parse::feature_err};
use rustc_session::lint;
use rustc_session::lint::builtin::BARE_TRAIT_OBJECTS;
use rustc_session::parse::feature_err;
use rustc_span::source_map::{original_sp, DUMMY_SP};
use rustc_span::symbol::{kw, sym, Ident};
use rustc_span::{self, BytePos, MultiSpan, Span};
@@ -472,7 +475,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}

pub fn to_ty(&self, ast_t: &hir::Ty<'_>) -> Ty<'tcx> {
let t = AstConv::ast_ty_to_ty(self, ast_t);
let t = <dyn AstConv<'_>>::ast_ty_to_ty(self, ast_t);
self.register_wf_obligation(t.into(), ast_t.span, traits::MiscObligation);
t
}
@@ -854,7 +857,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// out unconstrained or ambiguous, as we're
// just trying to get hints here.
self.save_and_restore_in_snapshot_flag(|_| {
let mut fulfill = TraitEngine::new(self.tcx);
let mut fulfill = <dyn TraitEngine<'_>>::new(self.tcx);
for obligation in ok.obligations {
fulfill.register_predicate_obligation(self, obligation);
}
@@ -947,6 +950,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
result
});

if result.is_ok() {
self.maybe_lint_bare_trait(qpath, hir_id);
}

// Write back the new resolution.
self.write_resolution(hir_id, result);
(
@@ -956,6 +963,29 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
)
}

fn maybe_lint_bare_trait(&self, qpath: &QPath<'_>, hir_id: hir::HirId) {
if let QPath::TypeRelative(self_ty, _) = qpath {
if let TyKind::TraitObject([poly_trait_ref, ..], _, TraitObjectSyntax::None) =
self_ty.kind
{
self.tcx.struct_span_lint_hir(BARE_TRAIT_OBJECTS, hir_id, self_ty.span, |lint| {
let mut db = lint
.build(&format!("trait objects without an explicit `dyn` are deprecated"));
let (sugg, app) = match self.tcx.sess.source_map().span_to_snippet(self_ty.span)
{
Ok(s) if poly_trait_ref.trait_ref.path.is_global() => {
(format!("<dyn ({})>", s), Applicability::MachineApplicable)
}
Ok(s) => (format!("<dyn {}>", s), Applicability::MachineApplicable),
Err(_) => ("<dyn <type>>".to_string(), Applicability::HasPlaceholders),
};
db.span_suggestion(self_ty.span, "use `dyn`", sugg, app);
db.emit()
});
}
}
}

/// Given a function `Node`, return its `FnDecl` if it exists, or `None` otherwise.
pub(in super::super) fn get_node_fn_decl(
&self,
@@ -1174,9 +1204,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {

let path_segs = match res {
Res::Local(_) | Res::SelfCtor(_) => vec![],
Res::Def(kind, def_id) => {
AstConv::def_ids_for_value_path_segments(self, segments, self_ty, kind, def_id)
}
Res::Def(kind, def_id) => <dyn AstConv<'_>>::def_ids_for_value_path_segments(
self, segments, self_ty, kind, def_id,
),
_ => bug!("instantiate_value_path on {:?}", res),
};

@@ -1219,7 +1249,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// errors if type parameters are provided in an inappropriate place.

let generic_segs: FxHashSet<_> = path_segs.iter().map(|PathSeg(_, index)| index).collect();
let generics_has_err = AstConv::prohibit_generics(
let generics_has_err = <dyn AstConv<'_>>::prohibit_generics(
self,
segments.iter().enumerate().filter_map(|(index, seg)| {
if !generic_segs.contains(&index) || is_alias_variant_ctor {
@@ -1262,7 +1292,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if let GenericArgCountResult {
correct: Err(GenericArgCountMismatch { reported: Some(_), .. }),
..
} = AstConv::check_generic_arg_count_for_call(
} = <dyn AstConv<'_>>::check_generic_arg_count_for_call(
tcx,
span,
def_id,
@@ -1370,7 +1400,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
) -> subst::GenericArg<'tcx> {
match (&param.kind, arg) {
(GenericParamDefKind::Lifetime, GenericArg::Lifetime(lt)) => {
AstConv::ast_region_to_region(self.fcx, lt, Some(param)).into()
<dyn AstConv<'_>>::ast_region_to_region(self.fcx, lt, Some(param)).into()
}
(GenericParamDefKind::Type { .. }, GenericArg::Type(ty)) => {
self.fcx.to_ty(ty).into()
@@ -1423,7 +1453,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}

let substs = self_ctor_substs.unwrap_or_else(|| {
AstConv::create_substs_for_generic_args(
<dyn AstConv<'_>>::create_substs_for_generic_args(
tcx,
def_id,
&[][..],
9 changes: 5 additions & 4 deletions compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
Original file line number Diff line number Diff line change
@@ -875,7 +875,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
match *qpath {
QPath::Resolved(ref maybe_qself, ref path) => {
let self_ty = maybe_qself.as_ref().map(|qself| self.to_ty(qself));
let ty = AstConv::res_to_ty(self, self_ty, path, true);
let ty = <dyn AstConv<'_>>::res_to_ty(self, self_ty, path, true);
(path.res, ty)
}
QPath::TypeRelative(ref qself, ref segment) => {
@@ -886,8 +886,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
} else {
Res::Err
};
let result =
AstConv::associated_path_to_ty(self, hir_id, path_span, ty, res, segment, true);
let result = <dyn AstConv<'_>>::associated_path_to_ty(
self, hir_id, path_span, ty, res, segment, true,
);
let ty = result.map(|(ty, _, _)| ty).unwrap_or_else(|_| self.tcx().ty_error());
let result = result.map(|(_, kind, def_id)| (kind, def_id));

@@ -1000,7 +1001,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// would trigger in `is_send::<T::AssocType>();`
// from `typeck-default-trait-impl-assoc-type.rs`.
} else {
let ty = AstConv::ast_ty_to_ty(self, hir_ty);
let ty = <dyn AstConv<'_>>::ast_ty_to_ty(self, hir_ty);
let ty = self.resolve_vars_if_possible(ty);
if ty == predicate.self_ty() {
error.obligation.cause.make_mut().span = hir_ty.span;
4 changes: 2 additions & 2 deletions compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs
Original file line number Diff line number Diff line change
@@ -461,7 +461,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// are not, the expectation must have been caused by something else.
debug!("suggest_missing_return_type: return type {:?} node {:?}", ty, ty.kind);
let sp = ty.span;
let ty = AstConv::ast_ty_to_ty(self, ty);
let ty = <dyn AstConv<'_>>::ast_ty_to_ty(self, ty);
debug!("suggest_missing_return_type: return type {:?}", ty);
debug!("suggest_missing_return_type: expected type {:?}", ty);
if ty.kind() == expected.kind() {
@@ -486,7 +486,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
let found = self.resolve_vars_with_obligations(found);
if let hir::FnRetTy::Return(ty) = fn_decl.output {
let ty = AstConv::ast_ty_to_ty(self, ty);
let ty = <dyn AstConv<'_>>::ast_ty_to_ty(self, ty);
let ty = self.tcx.erase_late_bound_regions(Binder::bind(ty));
let ty = self.normalize_associated_types_in(expr.span, ty);
if self.can_coerce(found, ty) {
2 changes: 1 addition & 1 deletion compiler/rustc_typeck/src/check/inherited.rs
Original file line number Diff line number Diff line change
@@ -117,7 +117,7 @@ impl Inherited<'a, 'tcx> {
maybe_typeck_results: infcx.in_progress_typeck_results,
},
infcx,
fulfillment_cx: RefCell::new(TraitEngine::new(tcx)),
fulfillment_cx: RefCell::new(<dyn TraitEngine<'_>>::new(tcx)),
locals: RefCell::new(Default::default()),
deferred_sized_obligations: RefCell::new(Vec::new()),
deferred_call_resolutions: RefCell::new(Default::default()),
Loading