]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #96353 - estebank:issue-95413, r=compiler-errors
authorbors <bors@rust-lang.org>
Wed, 4 May 2022 01:58:23 +0000 (01:58 +0000)
committerbors <bors@rust-lang.org>
Wed, 4 May 2022 01:58:23 +0000 (01:58 +0000)
When suggesting to import an item, also suggest changing the path if appropriate

When we don't find an item we search all of them for an appropriate
import and suggest `use`ing it. This is sometimes done for expressions
that have paths with more than one segment. We now also suggest changing
that path to work with the `use`.

Fix #95413

1  2 
compiler/rustc_resolve/src/late.rs

index 3db4d4481b4ecabce09e0710d98f60cabf343986,21c9461a83d9a866968fa577a55e647cd6d6cfad..1bdf53cf84fedc41a6b3194b9fc3fd9a55f2fd6a
@@@ -94,12 -94,6 +94,12 @@@ crate enum HasGenericParams 
      No,
  }
  
 +impl HasGenericParams {
 +    fn force_yes_if(self, b: bool) -> Self {
 +        if b { Self::Yes } else { self }
 +    }
 +}
 +
  #[derive(Copy, Clone, Debug, Eq, PartialEq)]
  crate enum ConstantItemKind {
      Const,
@@@ -131,9 -125,9 +131,9 @@@ crate enum RibKind<'a> 
  
      /// We're in a constant item. Can't refer to dynamic stuff.
      ///
 -    /// The `bool` indicates if this constant may reference generic parameters
 -    /// and is used to only allow generic parameters to be used in trivial constant expressions.
 -    ConstantItemRibKind(bool, Option<(Ident, ConstantItemKind)>),
 +    /// The item may reference generic parameters in trivial constant expressions.
 +    /// All other constants aren't allowed to use generic params at all.
 +    ConstantItemRibKind(HasGenericParams, Option<(Ident, ConstantItemKind)>),
  
      /// We passed through a module.
      ModuleRibKind(Module<'a>),
@@@ -396,10 -390,13 +396,10 @@@ impl<'a> PathSource<'a> 
                  ) | Res::Local(..)
                      | Res::SelfCtor(..)
              ),
 -            PathSource::Pat => matches!(
 -                res,
 -                Res::Def(
 -                    DefKind::Ctor(_, CtorKind::Const) | DefKind::Const | DefKind::AssocConst,
 -                    _,
 -                ) | Res::SelfCtor(..)
 -            ),
 +            PathSource::Pat => {
 +                res.expected_in_unit_struct_pat()
 +                    || matches!(res, Res::Def(DefKind::Const | DefKind::AssocConst, _))
 +            }
              PathSource::TupleStruct(..) => res.expected_in_tuple_struct_pat(),
              PathSource::Struct => matches!(
                  res,
@@@ -829,24 -826,19 +829,24 @@@ impl<'a: 'ast, 'ast> Visitor<'ast> for 
                              // Note that we might not be inside of an repeat expression here,
                              // but considering that `IsRepeatExpr` is only relevant for
                              // non-trivial constants this is doesn't matter.
 -                            self.with_constant_rib(IsRepeatExpr::No, true, None, |this| {
 -                                this.smart_resolve_path(
 -                                    ty.id,
 -                                    qself.as_ref(),
 -                                    path,
 -                                    PathSource::Expr(None),
 -                                );
 -
 -                                if let Some(ref qself) = *qself {
 -                                    this.visit_ty(&qself.ty);
 -                                }
 -                                this.visit_path(path, ty.id);
 -                            });
 +                            self.with_constant_rib(
 +                                IsRepeatExpr::No,
 +                                HasGenericParams::Yes,
 +                                None,
 +                                |this| {
 +                                    this.smart_resolve_path(
 +                                        ty.id,
 +                                        qself.as_ref(),
 +                                        path,
 +                                        PathSource::Expr(None),
 +                                    );
 +
 +                                    if let Some(ref qself) = *qself {
 +                                        this.visit_ty(&qself.ty);
 +                                    }
 +                                    this.visit_path(path, ty.id);
 +                                },
 +                            );
  
                              self.diagnostic_metadata.currently_processing_generics = prev;
                              return;
@@@ -1692,7 -1684,7 +1692,7 @@@ impl<'a: 'ast, 'b, 'ast> LateResolution
                                                      // not used as part of the type system, this is far less surprising.
                                                      this.with_constant_rib(
                                                          IsRepeatExpr::No,
 -                                                        true,
 +                                                        HasGenericParams::Yes,
                                                          None,
                                                          |this| this.visit_expr(expr),
                                                      );
                          // so it doesn't matter whether this is a trivial constant.
                          this.with_constant_rib(
                              IsRepeatExpr::No,
 -                            true,
 +                            HasGenericParams::Yes,
                              Some((item.ident, constant_item_kind)),
                              |this| this.visit_expr(expr),
                          );
      // Note that we intentionally still forbid `[0; N + 1]` during
      // name resolution so that we don't extend the future
      // compat lint to new cases.
 +    #[instrument(level = "debug", skip(self, f))]
      fn with_constant_rib(
          &mut self,
          is_repeat: IsRepeatExpr,
 -        is_trivial: bool,
 +        may_use_generics: HasGenericParams,
          item: Option<(Ident, ConstantItemKind)>,
          f: impl FnOnce(&mut Self),
      ) {
 -        debug!("with_constant_rib: is_repeat={:?} is_trivial={}", is_repeat, is_trivial);
 -        self.with_rib(ValueNS, ConstantItemRibKind(is_trivial, item), |this| {
 +        self.with_rib(ValueNS, ConstantItemRibKind(may_use_generics, item), |this| {
              this.with_rib(
                  TypeNS,
 -                ConstantItemRibKind(is_repeat == IsRepeatExpr::Yes || is_trivial, item),
 +                ConstantItemRibKind(
 +                    may_use_generics.force_yes_if(is_repeat == IsRepeatExpr::Yes),
 +                    item,
 +                ),
                  |this| {
 -                    this.with_label_rib(ConstantItemRibKind(is_trivial, item), f);
 +                    this.with_label_rib(ConstantItemRibKind(may_use_generics, item), f);
                  },
              )
          });
                                                          // not used as part of the type system, this is far less surprising.
                                                          this.with_constant_rib(
                                                              IsRepeatExpr::No,
 -                                                            true,
 +                                                            HasGenericParams::Yes,
                                                              None,
                                                              |this| {
                                                                  visit::walk_assoc_item(
                      def_id,
                      instead,
                      suggestion,
+                     path: path.into(),
                  });
              }
  
                      def_id,
                      instead: false,
                      suggestion: None,
+                     path: path.into(),
                  });
              } else {
                  err.cancel();
          debug!("resolve_anon_const {:?} is_repeat: {:?}", constant, is_repeat);
          self.with_constant_rib(
              is_repeat,
 -            constant.value.is_potential_trivial_const_param(),
 +            if constant.value.is_potential_trivial_const_param() {
 +                HasGenericParams::Yes
 +            } else {
 +                HasGenericParams::No
 +            },
              None,
              |this| visit::walk_anon_const(this, constant),
          );
                      if const_args.contains(&idx) {
                          self.with_constant_rib(
                              IsRepeatExpr::No,
 -                            argument.is_potential_trivial_const_param(),
 +                            if argument.is_potential_trivial_const_param() {
 +                                HasGenericParams::Yes
 +                            } else {
 +                                HasGenericParams::No
 +                            },
                              None,
                              |this| {
                                  this.resolve_expr(argument, None);