Repository: rust-lang/rust-analyzer
Pull request #13546 (2022-11-04 20:17:37)

Lower unsafety of fn pointer and fn item types


Patch:
diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml
index b070dd3406..422fe29f9d 100644
--- a/.github/workflows/release.yaml
+++ b/.github/workflows/release.yaml
@@ -257,7 +257,8 @@ jobs:
       - name: Publish Extension (OpenVSX, release)
         if: github.ref == 'refs/heads/release' && (github.repository == 'rust-analyzer/rust-analyzer' || github.repository == 'rust-lang/rust-analyzer')
         working-directory: ./editors/code
-        run: npx ovsx publish --pat ${{ secrets.OPENVSX_TOKEN }} --packagePath ../../dist/rust-analyzer-*.vsix
+        # token from https://dev.azure.com/rust-analyzer/
+        run: npx ovsx publish --pat ${{ secrets.OPENVSX_TOKEN }} --packagePath ../../dist/rust-analyzer-*.vsix || true
         timeout-minutes: 2
 
       - name: Publish Extension (Code Marketplace, nightly)
@@ -268,5 +269,5 @@ jobs:
       - name: Publish Extension (OpenVSX, nightly)
         if: github.ref != 'refs/heads/release' && (github.repository == 'rust-analyzer/rust-analyzer' || github.repository == 'rust-lang/rust-analyzer')
         working-directory: ./editors/code
-        run: npx ovsx publish --pat ${{ secrets.OPENVSX_TOKEN }} --packagePath ../../dist/rust-analyzer-*.vsix
+        run: npx ovsx publish --pat ${{ secrets.OPENVSX_TOKEN }} --packagePath ../../dist/rust-analyzer-*.vsix || true
         timeout-minutes: 2
diff --git a/crates/hir-def/src/pretty.rs b/crates/hir-def/src/pretty.rs
index 6636c8a23c..933970d10e 100644
--- a/crates/hir-def/src/pretty.rs
+++ b/crates/hir-def/src/pretty.rs
@@ -143,9 +143,12 @@ pub(crate) fn print_type_ref(type_ref: &TypeRef, buf: &mut dyn Write) -> fmt::Re
             print_type_ref(elem, buf)?;
             write!(buf, "]")?;
         }
-        TypeRef::Fn(args_and_ret, varargs) => {
+        TypeRef::Fn(args_and_ret, varargs, is_unsafe) => {
             let ((_, return_type), args) =
                 args_and_ret.split_last().expect("TypeRef::Fn is missing return type");
+            if *is_unsafe {
+                write!(buf, "unsafe ")?;
+            }
             write!(buf, "fn(")?;
             for (i, (_, typeref)) in args.iter().enumerate() {
                 if i != 0 {
diff --git a/crates/hir-def/src/type_ref.rs b/crates/hir-def/src/type_ref.rs
index 5b4c71be7f..f8bb78ddcf 100644
--- a/crates/hir-def/src/type_ref.rs
+++ b/crates/hir-def/src/type_ref.rs
@@ -119,7 +119,7 @@ pub enum TypeRef {
     Array(Box<TypeRef>, ConstScalarOrPath),
     Slice(Box<TypeRef>),
     /// A fn pointer. Last element of the vector is the return type.
-    Fn(Vec<(Option<Name>, TypeRef)>, bool /*varargs*/),
+    Fn(Vec<(Option<Name>, TypeRef)>, bool /*varargs*/, bool /*is_unsafe*/),
     ImplTrait(Vec<Interned<TypeBound>>),
     DynTrait(Vec<Interned<TypeBound>>),
     Macro(AstId<ast::MacroCall>),
@@ -229,7 +229,7 @@ impl TypeRef {
                     Vec::new()
                 };
                 params.push((None, ret_ty));
-                TypeRef::Fn(params, is_varargs)
+                TypeRef::Fn(params, is_varargs, inner.unsafe_token().is_some())
             }
             // for types are close enough for our purposes to the inner type for now...
             ast::Type::ForType(inner) => TypeRef::from_ast_opt(ctx, inner.ty()),
@@ -263,7 +263,7 @@ impl TypeRef {
         fn go(type_ref: &TypeRef, f: &mut impl FnMut(&TypeRef)) {
             f(type_ref);
             match type_ref {
-                TypeRef::Fn(params, _) => {
+                TypeRef::Fn(params, _, _) => {
                     params.iter().for_each(|(_, param_type)| go(param_type, f))
                 }
                 TypeRef::Tuple(types) => types.iter().for_each(|t| go(t, f)),
diff --git a/crates/hir-ty/src/display.rs b/crates/hir-ty/src/display.rs
index 5ad6613263..a22a4b170f 100644
--- a/crates/hir-ty/src/display.rs
+++ b/crates/hir-ty/src/display.rs
@@ -1187,8 +1187,11 @@ impl HirDisplay for TypeRef {
                 inner.hir_fmt(f)?;
                 write!(f, "]")?;
             }
-            TypeRef::Fn(parameters, is_varargs) => {
+            &TypeRef::Fn(ref parameters, is_varargs, is_unsafe) => {
                 // FIXME: Function pointer qualifiers.
+                if is_unsafe {
+                    write!(f, "unsafe ")?;
+                }
                 write!(f, "fn(")?;
                 if let Some(((_, return_type), function_parameters)) = parameters.split_last() {
                     for index in 0..function_parameters.len() {
@@ -1203,7 +1206,7 @@ impl HirDisplay for TypeRef {
                             write!(f, ", ")?;
                         }
                     }
-                    if *is_varargs {
+                    if is_varargs {
                         write!(f, "{}...", if parameters.len() == 1 { "" } else { ", " })?;
                     }
                     write!(f, ")")?;
diff --git a/crates/hir-ty/src/lib.rs b/crates/hir-ty/src/lib.rs
index 2b5989c6c6..b68c764bdc 100644
--- a/crates/hir-ty/src/lib.rs
+++ b/crates/hir-ty/src/lib.rs
@@ -210,6 +210,7 @@ pub(crate) fn make_binders<T: HasInterner<Interner = Interner>>(
 pub struct CallableSig {
     params_and_return: Arc<[Ty]>,
     is_varargs: bool,
+    safety: Safety,
 }
 
 has_interner!(CallableSig);
@@ -218,9 +219,14 @@ has_interner!(CallableSig);
 pub type PolyFnSig = Binders<CallableSig>;
 
 impl CallableSig {
-    pub fn from_params_and_return(mut params: Vec<Ty>, ret: Ty, is_varargs: bool) -> CallableSig {
+    pub fn from_params_and_return(
+        mut params: Vec<Ty>,
+        ret: Ty,
+        is_varargs: bool,
+        safety: Safety,
+    ) -> CallableSig {
         params.push(ret);
-        CallableSig { params_and_return: params.into(), is_varargs }
+        CallableSig { params_and_return: params.into(), is_varargs, safety }
     }
 
     pub fn from_fn_ptr(fn_ptr: &FnPointer) -> CallableSig {
@@ -237,13 +243,14 @@ impl CallableSig {
                 .map(|arg| arg.assert_ty_ref(Interner).clone())
                 .collect(),
             is_varargs: fn_ptr.sig.variadic,
+            safety: fn_ptr.sig.safety,
         }
     }
 
     pub fn to_fn_ptr(&self) -> FnPointer {
         FnPointer {
             num_binders: 0,
-            sig: FnSig { abi: (), safety: Safety::Safe, variadic: self.is_varargs },
+            sig: FnSig { abi: (), safety: self.safety, variadic: self.is_varargs },
             substitution: FnSubst(Substitution::from_iter(
                 Interner,
                 self.params_and_return.iter().cloned(),
@@ -268,7 +275,11 @@ impl TypeFoldable<Interner> for CallableSig {
     ) -> Result<Self, E> {
         let vec = self.params_and_return.to_vec();
         let folded = vec.try_fold_with(folder, outer_binder)?;
-        Ok(CallableSig { params_and_return: folded.into(), is_varargs: self.is_varargs })
+        Ok(CallableSig {
+            params_and_return: folded.into(),
+            is_varargs: self.is_varargs,
+            safety: self.safety,
+        })
     }
 }
 
@@ -573,5 +584,5 @@ pub fn callable_sig_from_fnonce(
 
     let ret_ty = db.normalize_projection(projection, env);
 
-    Some(CallableSig::from_params_and_return(params, ret_ty.clone(), false))
+    Some(CallableSig::from_params_and_return(params, ret_ty.clone(), false, Safety::Safe))
 }
diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs
index 22a85cf154..baf9842d5f 100644
--- a/crates/hir-ty/src/lower.rs
+++ b/crates/hir-ty/src/lower.rs
@@ -227,13 +227,17 @@ impl<'a> TyLoweringContext<'a> {
                     .intern(Interner)
             }
             TypeRef::Placeholder => TyKind::Error.intern(Interner),
-            TypeRef::Fn(params, is_varargs) => {
+            &TypeRef::Fn(ref params, variadic, is_unsafe) => {
                 let substs = self.with_shifted_in(DebruijnIndex::ONE, |ctx| {
                     Substitution::from_iter(Interner, params.iter().map(|(_, tr)| ctx.lower_ty(tr)))
                 });
                 TyKind::Function(FnPointer {
                     num_binders: 0, // FIXME lower `for<'a> fn()` correctly
-                    sig: FnSig { abi: (), safety: Safety::Safe, variadic: *is_varargs },
+                    sig: FnSig {
+                        abi: (),
+                        safety: if is_unsafe { Safety::Unsafe } else { Safety::Safe },
+                        variadic,
+                    },
                     substitution: FnSubst(substs),
                 })
                 .intern(Interner)
@@ -1573,7 +1577,12 @@ fn fn_sig_for_fn(db: &dyn HirDatabase, def: FunctionId) -> PolyFnSig {
         .with_type_param_mode(ParamLoweringMode::Variable);
     let ret = ctx_ret.lower_ty(&data.ret_type);
     let generics = generics(db.upcast(), def.into());
-    let sig = CallableSig::from_params_and_return(params, ret, data.is_varargs());
+    let sig = CallableSig::from_params_and_return(
+        params,
+        ret,
+        data.is_varargs(),
+        if data.has_unsafe_kw() { Safety::Unsafe } else { Safety::Safe },
+    );
     make_binders(db, &generics, sig)
 }
 
@@ -1617,7 +1626,7 @@ fn fn_sig_for_struct_constructor(db: &dyn HirDatabase, def: StructId) -> PolyFnS
         TyLoweringContext::new(db, &resolver).with_type_param_mode(ParamLoweringMode::Variable);
     let params = fields.iter().map(|(_, field)| ctx.lower_ty(&field.type_ref)).collect::<Vec<_>>();
     let (ret, binders) = type_for_adt(db, def.into()).into_value_and_skipped_binders();
-    Binders::new(binders, CallableSig::from_params_and_return(params, ret, false))
+    Binders::new(binders, CallableSig::from_params_and_return(params, ret, false, Safety::Safe))
 }
 
 /// Build the type of a tuple struct constructor.
@@ -1644,7 +1653,7 @@ fn fn_sig_for_enum_variant_constructor(db: &dyn HirDatabase, def: EnumVariantId)
         TyLoweringContext::new(db, &resolver).with_type_param_mode(ParamLoweringMode::Variable);
     let params = fields.iter().map(|(_, field)| ctx.lower_ty(&field.type_ref)).collect::<Vec<_>>();
     let (ret, binders) = type_for_adt(db, def.parent.into()).into_value_and_skipped_binders();
-    Binders::new(binders, CallableSig::from_params_and_return(params, ret, false))
+    Binders::new(binders, CallableSig::from_params_and_return(params, ret, false, Safety::Safe))
 }
 
 /// Build the type of a tuple enum variant constructor.
diff --git a/crates/ide/src/moniker.rs b/crates/ide/src/moniker.rs
index 07d117aff1..852a8fd837 100644
--- a/crates/ide/src/moniker.rs
+++ b/crates/ide/src/moniker.rs
@@ -73,8 +73,8 @@ impl MonikerResult {
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub struct PackageInformation {
     pub name: String,
-    pub repo: Option<String>,
-    pub version: Option<String>,
+    pub repo: String,
+    pub version: String,
 }
 
 pub(crate) fn crate_for_file(db: &RootDatabase, file_id: FileId) -> Option<Crate> {
@@ -256,18 +256,18 @@ pub(crate) fn def_to_moniker(
             let (name, repo, version) = match krate.origin(db) {
                 CrateOrigin::CratesIo { repo, name } => (
                     name.unwrap_or(krate.display_name(db)?.canonical_name().to_string()),
-                    repo,
-                    krate.version(db),
+                    repo?,
+                    krate.version(db)?,
                 ),
                 CrateOrigin::Lang(lang) => (
                     krate.display_name(db)?.canonical_name().to_string(),
-                    Some("https://github.com/rust-lang/rust/".to_string()),
-                    Some(match lang {
+                    "https://github.com/rust-lang/rust/".to_string(),
+                    match lang {
                         LangCrateOrigin::Other => {
                             "https://github.com/rust-lang/rust/library/".into()
                         }
                         lang => format!("https://github.com/rust-lang/rust/library/{lang}",),
-                    }),
+                    },
                 ),
             };
             PackageInformation { name, repo, version }
@@ -315,7 +315,7 @@ pub mod module {
 }
 "#,
             "foo::module::func",
-            r#"PackageInformation { name: "foo", repo: Some("https://a.b/foo.git"), version: Some("0.1.0") }"#,
+            r#"PackageInformation { name: "foo", repo: "https://a.b/foo.git", version: "0.1.0" }"#,
             MonikerKind::Import,
         );
         check_moniker(
@@ -331,7 +331,7 @@ pub mod module {
 }
 "#,
             "foo::module::func",
-            r#"PackageInformation { name: "foo", repo: Some("https://a.b/foo.git"), version: Some("0.1.0") }"#,
+            r#"PackageInformation { name: "foo", repo: "https://a.b/foo.git", version: "0.1.0" }"#,
             MonikerKind::Export,
         );
     }
@@ -348,7 +348,7 @@ pub mod module {
 }
 "#,
             "foo::module::MyTrait::func",
-            r#"PackageInformation { name: "foo", repo: Some("https://a.b/foo.git"), version: Some("0.1.0") }"#,
+            r#"PackageInformation { name: "foo", repo: "https://a.b/foo.git", version: "0.1.0" }"#,
             MonikerKind::Export,
         );
     }
@@ -365,7 +365,7 @@ pub mod module {
 }
 "#,
             "foo::module::MyTrait::MY_CONST",
-            r#"PackageInformation { name: "foo", repo: Some("https://a.b/foo.git"), version: Some("0.1.0") }"#,
+            r#"PackageInformation { name: "foo", repo: "https://a.b/foo.git", version: "0.1.0" }"#,
             MonikerKind::Export,
         );
     }
@@ -382,7 +382,7 @@ pub mod module {
 }
 "#,
             "foo::module::MyTrait::MyType",
-            r#"PackageInformation { name: "foo", repo: Some("https://a.b/foo.git"), version: Some("0.1.0") }"#,
+            r#"PackageInformation { name: "foo", repo: "https://a.b/foo.git", version: "0.1.0" }"#,
             MonikerKind::Export,
         );
     }
@@ -405,7 +405,7 @@ pub mod module {
 }
 "#,
             "foo::module::MyStruct::MyTrait::func",
-            r#"PackageInformation { name: "foo", repo: Some("https://a.b/foo.git"), version: Some("0.1.0") }"#,
+            r#"PackageInformation { name: "foo", repo: "https://a.b/foo.git", version: "0.1.0" }"#,
             MonikerKind::Export,
         );
     }
@@ -425,7 +425,7 @@ pub struct St {
 }
 "#,
             "foo::St::a",
-            r#"PackageInformation { name: "foo", repo: Some("https://a.b/foo.git"), version: Some("0.1.0") }"#,
+            r#"PackageInformation { name: "foo", repo: "https://a.b/foo.git", version: "0.1.0" }"#,
             MonikerKind::Import,
         );
     }
diff --git a/crates/rust-analyzer/src/cli/lsif.rs b/crates/rust-analyzer/src/cli/lsif.rs
index c74ddabb17..5ff347b9bd 100644
--- a/crates/rust-analyzer/src/cli/lsif.rs
+++ b/crates/rust-analyzer/src/cli/lsif.rs
@@ -106,12 +106,12 @@ impl LsifManager<'_> {
                 manager: "cargo".to_string(),
                 uri: None,
                 content: None,
-                repository: pi.repo.map(|url| lsif::Repository {
-                    url,
+                repository: Some(lsif::Repository {
+                    url: pi.repo,
                     r#type: "git".to_string(),
                     commit_id: None,
                 }),
-                version: pi.version,
+                version: Some(pi.version),
             }));
         self.package_map.insert(package_information, result_set_id);
         result_set_id
diff --git a/crates/rust-analyzer/src/cli/scip.rs b/crates/rust-analyzer/src/cli/scip.rs
index ca7ba896b6..16298862b5 100644
--- a/crates/rust-analyzer/src/cli/scip.rs
+++ b/crates/rust-analyzer/src/cli/scip.rs
@@ -231,7 +231,7 @@ fn token_to_symbol(token: &TokenStaticData) -> Option<scip_types::Symbol> {
         package: Some(scip_types::Package {
             manager: "cargo".to_string(),
             name: package_name,
-            version: version.unwrap_or_else(|| ".".to_string()),
+            version,
             ..Default::default()
         })
         .into(),
@@ -415,42 +415,4 @@ pub mod module {
             "",
         );
     }
-
-    #[test]
-    fn global_symbol_for_pub_struct() {
-        check_symbol(
-            r#"
-    //- /lib.rs crate:main
-    mod foo;
-
-    fn main() {
-        let _bar = foo::Bar { i: 0 };
-    }
-    //- /foo.rs
-    pub struct Bar$0 {
-        pub i: i32,
-    }
-    "#,
-            "rust-analyzer cargo main . foo/Bar#",
-        );
-    }
-
-    #[test]
-    fn global_symbol_for_pub_struct_reference() {
-        check_symbol(
-            r#"
-    //- /lib.rs crate:main
-    mod foo;
-
-    fn main() {
-        let _bar = foo::Bar$0 { i: 0 };
-    }
-    //- /foo.rs
-    pub struct Bar {
-        pub i: i32,
-    }
-    "#,
-            "rust-analyzer cargo main . foo/Bar#",
-        );
-    }
 }
diff --git a/editors/code/package-lock.json b/editors/code/package-lock.json
index 0b25564e28..a72865d4fe 100644
--- a/editors/code/package-lock.json
+++ b/editors/code/package-lock.json
@@ -23,7 +23,7 @@
                 "esbuild": "^0.14.48",
                 "eslint": "^8.19.0",
                 "eslint-config-prettier": "^8.5.0",
-                "ovsx": "^0.5.2",
+                "ovsx": "^0.5.1",
                 "prettier": "^2.7.1",
                 "tslib": "^2.4.0",
                 "typescript": "^4.7.4",
@@ -2874,9 +2874,9 @@
             }
         },
         "node_modules/ovsx": {
-            "version": "0.5.2",
-            "resolved": "https://registry.npmjs.org/ovsx/-/ovsx-0.5.2.tgz",
-            "integrity": "sha512-UbLultRCk46WddeA0Cly4hoRhzBJUiLgbIEViXlgOvV54LbsppClDkMLoCevUUBHoiNdMX2NuiSgURAEXgCZdw==",
+            "version": "0.5.1",
+            "resolved": "https://registry.npmjs.org/ovsx/-/ovsx-0.5.1.tgz",
+            "integrity": "sha512-3OWq0l7DuVHi2bd2aQe5+QVQlFIqvrcw3/2vGXL404L6Tr+R4QHtzfnYYghv8CCa85xJHjU0RhcaC7pyXkAUbg==",
             "dev": true,
             "dependencies": {
                 "commander": "^6.1.0",
@@ -5958,9 +5958,9 @@
             }
         },
         "ovsx": {
-            "version": "0.5.2",
-            "resolved": "https://registry.npmjs.org/ovsx/-/ovsx-0.5.2.tgz",
-            "integrity": "sha512-UbLultRCk46WddeA0Cly4hoRhzBJUiLgbIEViXlgOvV54LbsppClDkMLoCevUUBHoiNdMX2NuiSgURAEXgCZdw==",
+            "version": "0.5.1",
+            "resolved": "https://registry.npmjs.org/ovsx/-/ovsx-0.5.1.tgz",
+            "integrity": "sha512-3OWq0l7DuVHi2bd2aQe5+QVQlFIqvrcw3/2vGXL404L6Tr+R4QHtzfnYYghv8CCa85xJHjU0RhcaC7pyXkAUbg==",
             "dev": true,
             "requires": {
                 "commander": "^6.1.0",
diff --git a/editors/code/package.json b/editors/code/package.json
index 8e8b59159d..0ff6652745 100644
--- a/editors/code/package.json
+++ b/editors/code/package.json
@@ -49,7 +49,7 @@
         "esbuild": "^0.14.48",
         "eslint": "^8.19.0",
         "eslint-config-prettier": "^8.5.0",
-        "ovsx": "^0.5.2",
+        "ovsx": "^0.5.1",
         "prettier": "^2.7.1",
         "tslib": "^2.4.0",
         "typescript": "^4.7.4",
diff --git a/triagebot.toml b/triagebot.toml
index a910e012b7..fa0824ac53 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -1,11 +1,1 @@
 [assign]
-
-[shortcut]
-
-[relabel]
-allow-unauthenticated = [
-    "S-*",
-]
-
-[autolabel."S-waiting-on-review"]
-new_pr = true


Test patch:
diff --git a/crates/hir-ty/src/tests/coercion.rs b/crates/hir-ty/src/tests/coercion.rs
index 1abdb0be7f..7e3aecc2ae 100644
--- a/crates/hir-ty/src/tests/coercion.rs
+++ b/crates/hir-ty/src/tests/coercion.rs
@@ -390,7 +390,7 @@ fn test() {
     let f: fn(u32) -> isize = foo;
                            // ^^^ adjustments: Pointer(ReifyFnPointer)
     let f: unsafe fn(u32) -> isize = foo;
-                                  // ^^^ adjustments: Pointer(ReifyFnPointer)
+                                  // ^^^ adjustments: Pointer(ReifyFnPointer), Pointer(UnsafeFnPointer)
 }",
     );
 }
@@ -421,7 +421,10 @@ fn coerce_closure_to_fn_ptr() {
     check_no_mismatches(
         r"
 fn test() {
-    let f: fn(u32) -> isize = |x| { 1 };
+    let f: fn(u32) -> u32 = |x| x;
+                         // ^^^^^ adjustments: Pointer(ClosureFnPointer(Safe))
+    let f: unsafe fn(u32) -> u32 = |x| x;
+                                // ^^^^^ adjustments: Pointer(ClosureFnPointer(Unsafe))
 }",
     );
 }