mirror of
				https://github.com/rust-lang/rust-analyzer.git
				synced 2025-11-04 05:35:55 +00:00 
			
		
		
		
	fix: Handle newstyle rustc_intrinsic safety correctly
				
					
				
			This commit is contained in:
		
							parent
							
								
									6725e046df
								
							
						
					
					
						commit
						e462ee79e4
					
				
					 2 changed files with 24 additions and 9 deletions
				
			
		| 
						 | 
				
			
			@ -270,17 +270,15 @@ pub fn is_fn_unsafe_to_call(db: &dyn HirDatabase, func: FunctionId) -> bool {
 | 
			
		|||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    let is_intrinsic = db.attrs(func.into()).by_key(&sym::rustc_intrinsic).exists()
 | 
			
		||||
        || data.abi.as_ref() == Some(&sym::rust_dash_intrinsic);
 | 
			
		||||
 | 
			
		||||
    let loc = func.lookup(db.upcast());
 | 
			
		||||
    match loc.container {
 | 
			
		||||
        hir_def::ItemContainerId::ExternBlockId(block) => {
 | 
			
		||||
            if is_intrinsic || {
 | 
			
		||||
                let id = block.lookup(db.upcast()).id;
 | 
			
		||||
                id.item_tree(db.upcast())[id.value].abi.as_ref() == Some(&sym::rust_dash_intrinsic)
 | 
			
		||||
            } {
 | 
			
		||||
                // Intrinsics are unsafe unless they have the rustc_safe_intrinsic attribute
 | 
			
		||||
            let id = block.lookup(db.upcast()).id;
 | 
			
		||||
            let is_intrinsic_block =
 | 
			
		||||
                id.item_tree(db.upcast())[id.value].abi.as_ref() == Some(&sym::rust_dash_intrinsic);
 | 
			
		||||
            if is_intrinsic_block {
 | 
			
		||||
                // legacy intrinsics
 | 
			
		||||
                // extern "rust-intrinsic" intrinsics are unsafe unless they have the rustc_safe_intrinsic attribute
 | 
			
		||||
                !db.attrs(func.into()).by_key(&sym::rustc_safe_intrinsic).exists()
 | 
			
		||||
            } else {
 | 
			
		||||
                // Function in an `extern` block are always unsafe to call, except when
 | 
			
		||||
| 
						 | 
				
			
			@ -288,7 +286,6 @@ pub fn is_fn_unsafe_to_call(db: &dyn HirDatabase, func: FunctionId) -> bool {
 | 
			
		|||
                !data.is_safe()
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        _ if is_intrinsic => !db.attrs(func.into()).by_key(&sym::rustc_safe_intrinsic).exists(),
 | 
			
		||||
        _ => false,
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -237,6 +237,24 @@ fn main() {
 | 
			
		|||
    fn no_missing_unsafe_diagnostic_with_safe_intrinsic() {
 | 
			
		||||
        check_diagnostics(
 | 
			
		||||
            r#"
 | 
			
		||||
#[rustc_intrinsic]
 | 
			
		||||
pub fn bitreverse(x: u32) -> u32; // Safe intrinsic
 | 
			
		||||
#[rustc_intrinsic]
 | 
			
		||||
pub unsafe fn floorf32(x: f32) -> f32; // Unsafe intrinsic
 | 
			
		||||
 | 
			
		||||
fn main() {
 | 
			
		||||
    let _ = bitreverse(12);
 | 
			
		||||
    let _ = floorf32(12.0);
 | 
			
		||||
          //^^^^^^^^^^^^^^💡 error: call to unsafe function is unsafe and requires an unsafe function or block
 | 
			
		||||
}
 | 
			
		||||
"#,
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[test]
 | 
			
		||||
    fn no_missing_unsafe_diagnostic_with_legacy_safe_intrinsic() {
 | 
			
		||||
        check_diagnostics(
 | 
			
		||||
            r#"
 | 
			
		||||
extern "rust-intrinsic" {
 | 
			
		||||
    #[rustc_safe_intrinsic]
 | 
			
		||||
    pub fn bitreverse(x: u32) -> u32; // Safe intrinsic
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue