Skip to content

Report missing cases of bare_trait_objects #82868

New issue

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

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

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Mar 18, 2021
Merged
Show file tree
Hide file tree
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
Expand Up @@ -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,
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_ast_lowering/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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)),
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_hir/src/hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir/src/intravisit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
5 changes: 4 additions & 1 deletion compiler/rustc_hir_pretty/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand Down Expand Up @@ -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 {
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_middle/src/ty/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,7 @@ impl<'v> hir::intravisit::Visitor<'v> for TraitObjectVisitor<'v> {
hir::LifetimeName::ImplicitObjectLifetimeDefault | hir::LifetimeName::Static,
..
},
_,
) => {
self.0.push(ty);
}
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_resolve/src/late/lifetimes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_trait_selection/src/infer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_traits/src/dropck_outlives.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
4 changes: 3 additions & 1 deletion compiler/rustc_typeck/src/astconv/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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)) => {
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_typeck/src/check/coercion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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());
Expand Down Expand Up @@ -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;
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_typeck/src/check/dropck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
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
Expand Up @@ -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};
Expand All @@ -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};
Expand Down Expand Up @@ -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
}
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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);
(
Expand All @@ -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,
Expand Down Expand Up @@ -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),
};

Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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,
&[][..],
Expand Down
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
Expand Up @@ -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) => {
Expand All @@ -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));

Expand Down Expand Up @@ -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;
Expand Down
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
Expand Up @@ -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() {
Expand All @@ -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) {
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_typeck/src/check/inherited.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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()),
Expand Down
Loading