Skip to content
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

crash: compile-time typeck/check.rs failure #3668

Closed
BigEndian opened this issue Oct 6, 2012 · 4 comments
Closed

crash: compile-time typeck/check.rs failure #3668

BigEndian opened this issue Oct 6, 2012 · 4 comments
Labels
A-resolve Area: Name resolution A-type-system Area: Type system I-ICE Issue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️
Milestone

Comments

@BigEndian
Copy link

Result of attempted compilation:

rust: task failed at 'Assertion fcx.inh.locals.contains_key(nid) failed', /Users/superjapanfreak/build/rust/src/rustc/middle/typeck/check.rs:2388
error: internal compiler error: unexpected failure
note: the compiler hit an unexpected failure path. this is a bug
note: try running with RUST_LOG=rustc=0,::rt::backtrace to get further details and report the results to github.com/mozilla/rust/issues
rust: task failed at 'explicit failure', /Users/superjapanfreak/build/rust/src/rustc/driver/rustc.rs:275
rust: domain main @0x7fb97b800010 root task failed
rust: task failed at 'killed', /Users/superjapanfreak/build/rust/src/libcore/task.rs:705
struct Employee { name: ~str, mut employer: Option<@Business> }                                                                                                                    
struct Business { name: ~str, mut boss: Option<@mut Employee>, mut employees: ~[Option<@mut Employee>] }                                                                           

trait EmployeeTrait {                                                                                                                                                              
   pure fn isEmployed() -> bool;                                                                                                                                                   
   fn setEmployer(employer: @Business);                                                                                                                                            
}                                                                                                                                                                                  

impl Employee: EmployeeTrait {                                                                                                                                                        pure fn isEmployed() -> bool {                                                                                                                                                        self.employer.is_some()                                                                                                                                                      
   }                                                                                                                                                                               
   fn setEmployer(employer: @Business) {                                                                                                                                           
      self.employer = Some(employer);                                                                                                                                              
   }                                                                                                                                                                               
}                                                                                                                                                                                  

trait BusinessTrait {                                                                                                                                                              
   fn fireBoss() -> bool;                                                                                                                                                          
   fn hireBoss(e: @mut Employee);                                                                                                                                                  
   fn getBossOption() -> Option<@Employee>;                                                                                                                                        
}                                                                                                                                                                                  

impl Business: BusinessTrait {                                                                                                                                                     
   fn fireBoss() -> bool {                                                                                                                                                         
      if self.boss.is_none() {                                                                                                                                                     
         return false;                                                                                                                                                             
      }                                                                                                                                                                            
      let oldBoss = self.boss.get();                                                                                                                                               
      oldBoss.employer = None;                                                                                                                                                     
      self.boss = None;                                                                                                                                                            
      true                                                                                                                                                                         
   }                                                                                                                                                                               
   fn hireBoss(newBoss: @mut Employee) {                                                                                                                                           
      if self.boss.is_some() {                                                                                                                                                     
         self.fireBoss();                                                                                                                                                          
      }                                                                                                                                                                            
      newBoss.setEmployer(@copy self);                                                                                                                                             
      self.boss = Some(newBoss);                                                                                                                                                   
   }                                                                                                                                                                               
   fn getBossOption() -> Option<@Employee> {                                                                                                                                       
      let opt: Option<@Employee> = None;                                                                                                                                           
      if self.boss.is_some() {                                                                                                                                                     
         const bossCopy: @Employee = self.boss.get();                                                                                                                              
         opt = Some(bossCopy);                                                                                                                                                     
      }                                                                                                                                                                            
      opt                                                                                                                                                                          
   }                                                                                                                                                                               
}                                                                                                                                                                                  

fn main() {                                                                                                                                                                        
   let bob = @mut Employee { name: ~"Bob Newhart", employer: None };
   let restaurant = Business { name: ~"In-N-Out", boss: Some(bob), employees: ~[] };                                                                                               

   io::println(#fmt("Bob is %s", if bob.isEmployed() { ~"employed" } else { ~"not employed" }));                                                                                   
} 
@BigEndian
Copy link
Author

Updated test case:

struct P { child: Option<@mut P> }                                                                                                                                                                                                                                                                                                                                    
trait PTrait {                                                                                                                                                                     
   fn getChildOption() -> Option<@P>;                                                                                                                                              
}                                                                                                                                                                                  

impl P: PTrait {                                                                                                                                                                   
   fn getChildOption() -> Option<@P> {                                                                                                                                             
      let opt: Option<@P> = None;                                                                                                                                                        if self.child.is_some() {                                                                                                                                                             const childVal: @P = self.child.get();                                                                                                                                    
         opt = Some(childVal);                                                                                                                                                     
      }                                                                                                                                                                            
      opt                                                                                                                                                                          
   }                                                                                                                                                                               
}

@ghost ghost assigned catamorphism Oct 6, 2012
@catamorphism
Copy link
Contributor

I'll take a look while waiting for snapshots to finish...

@catamorphism
Copy link
Contributor

An even smaller program that exhibits the same bug:

fn f(x:int) {
    const child: int = x + 1;
}

fn main() {}

The problem is that this isn't an acceptable RHS for a constant, as in your example as well. But, constant checking happens after typechecking. The typechecker, though, assumes constants don't refer to things like self or args. This is a bad assumption to make. To fix this, either we have to pass a function context to checking nested consts, or check constants before typechecking (constant checking uses some tables generated by the typechecker, though). It's a pain either way. But should be fixed.

@nikomatsakis
Copy link
Contributor

This seems like a resolve bug. Resolve should understand the scoping for constant declarations.

RalfJung pushed a commit to RalfJung/rust that referenced this issue Jun 29, 2024
…f_checked_ops, r=RalfJung

Use strict ops instead of checked ops

## What

Replace `checked_add(...).unwrap()` with `strict_add(...)`, etc.

Resolves rust-lang#3668.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-resolve Area: Name resolution A-type-system Area: Type system I-ICE Issue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️
Projects
None yet
Development

No branches or pull requests

3 participants