|
1 | 1 | use crate::diagnostics::{ImportSuggestion, LabelSuggestion, TypoSuggestion};
|
2 | 2 | use crate::late::{AliasPossibility, LateResolutionVisitor, RibKind};
|
3 | 3 | use crate::late::{LifetimeBinderKind, LifetimeRes, LifetimeRibKind, LifetimeUseSet};
|
| 4 | +use crate::ty::fast_reject::SimplifiedType; |
4 | 5 | use crate::{errors, path_names_to_string};
|
5 | 6 | use crate::{Module, ModuleKind, ModuleOrUniformRoot};
|
6 | 7 | use crate::{PathResult, PathSource, Segment};
|
@@ -1595,7 +1596,11 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
|
1595 | 1596 | Some(Vec::from(pattern_spans))
|
1596 | 1597 | }
|
1597 | 1598 | // e.g. `let _ = Enum::TupleVariant(field1, field2);`
|
1598 |
| - PathSource::Expr(Some(Expr { kind: ExprKind::Call(_, ref args), .. })) => { |
| 1599 | + PathSource::Expr(Some(Expr { |
| 1600 | + kind: ExprKind::Call(path, ref args), |
| 1601 | + span: call_span, |
| 1602 | + .. |
| 1603 | + })) => { |
1599 | 1604 | err.set_primary_message(
|
1600 | 1605 | "cannot initialize a tuple struct which contains private fields",
|
1601 | 1606 | );
|
@@ -1675,6 +1680,56 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
|
1675 | 1680 | );
|
1676 | 1681 | }
|
1677 | 1682 | }
|
| 1683 | + // We'd ideally use `type_implements_trait` but don't have access to |
| 1684 | + // the trait solver here. We can't use `get_diagnostic_item` or |
| 1685 | + // `all_traits` in resolve either. So instead we abuse the import |
| 1686 | + // suggestion machinery to get `std::default::Default` and perform some |
| 1687 | + // checks to confirm that we got *only* that trait. We then see if the |
| 1688 | + // Adt we have has a direct implementation of `Default`. If so, we |
| 1689 | + // provide a structured suggestion. |
| 1690 | + let default_trait = self |
| 1691 | + .r |
| 1692 | + .lookup_import_candidates( |
| 1693 | + Ident::with_dummy_span(sym::Default), |
| 1694 | + Namespace::TypeNS, |
| 1695 | + &self.parent_scope, |
| 1696 | + &|res: Res| matches!(res, Res::Def(DefKind::Trait, _)), |
| 1697 | + ) |
| 1698 | + .iter() |
| 1699 | + .filter_map(|candidate| candidate.did) |
| 1700 | + .filter(|did| { |
| 1701 | + self.r |
| 1702 | + .tcx |
| 1703 | + .get_attrs(*did, sym::rustc_diagnostic_item) |
| 1704 | + .any(|attr| attr.value_str() == Some(sym::Default)) |
| 1705 | + }) |
| 1706 | + .next(); |
| 1707 | + if let Some(default_trait) = default_trait |
| 1708 | + && self.r.extern_crate_map.iter().flat_map(|(_, crate_)| { |
| 1709 | + self |
| 1710 | + .r |
| 1711 | + .tcx |
| 1712 | + .implementations_of_trait((*crate_, default_trait)) |
| 1713 | + }) |
| 1714 | + .filter_map(|(_, simplified_self_ty)| *simplified_self_ty) |
| 1715 | + .filter_map(|simplified_self_ty| match simplified_self_ty { |
| 1716 | + SimplifiedType::Adt(did) => Some(did), |
| 1717 | + _ => None |
| 1718 | + }) |
| 1719 | + .any(|did| did == def_id) |
| 1720 | + { |
| 1721 | + err.multipart_suggestion( |
| 1722 | + "consider using the `Default` trait", |
| 1723 | + vec![ |
| 1724 | + (path.span.shrink_to_lo(), "<".to_string()), |
| 1725 | + ( |
| 1726 | + path.span.shrink_to_hi().with_hi(call_span.hi()), |
| 1727 | + " as std::default::Default>::default()".to_string(), |
| 1728 | + ), |
| 1729 | + ], |
| 1730 | + Applicability::MaybeIncorrect, |
| 1731 | + ); |
| 1732 | + } |
1678 | 1733 | }
|
1679 | 1734 | // Use spans of the tuple struct definition.
|
1680 | 1735 | self.r.field_def_ids(def_id).map(|field_ids| {
|
|
0 commit comments