diff --git a/src/etc/monodebug.pl b/src/etc/monodebug.pl new file mode 100755 index 000000000000..324c576a4bda --- /dev/null +++ b/src/etc/monodebug.pl @@ -0,0 +1,80 @@ +#!/usr/bin/perl + +# +# This is a tool that helps with debugging incorrect monomorphic instance collapse. +# +# To use: +# $ RUST_LOG=rustc::middle::trans::monomorphize rustc ARGS 2>&1 >log.txt +# $ ./monodebug.pl log.txt +# +# This will show all generics that got collapsed. You can inspect this list to find the instances +# that were mistakenly combined into one. Fixes will (most likely) be applied to type_use.rs. +# +# Questions about this tool go to pcwalton. +# + +use strict; +use warnings; +use Data::Dumper qw(Dumper); +use Text::Balanced qw(extract_bracketed); + +my %funcs; +while (<>) { + chomp; + /^rust: ~"monomorphic_fn\((.*)"$/ or next; + my $text = $1; + $text =~ /fn_id=(\{ crate: \d+, node: \d+ \} \([^)]+\)), real_substs=(.*?), substs=(.*?), hash_id = \@\{ (.*) \}$/ or next; + my ($fn_id, $real_substs, $substs, $hash_id) = ($1, $2, $3, $4); + + #print "$hash_id\n"; + $hash_id =~ /^def: { crate: \d+, node: \d+ }, params: ~\[ (.*) \], impl_did_opt: (?:None|Some\({ crate: \d+, node: \d+ }\))$/ or next; + my $params = $1; + + my @real_substs; + @real_substs = $real_substs =~ /\\"(.*?)\\"/g; + + my @mono_params; + while (1) { + $params =~ s/^, //; + if ($params =~ s/^mono_precise//) { + extract_bracketed($params, '()'); + push @mono_params, 'precise'; + next; + } + if ($params =~ s/^mono_repr//) { + my $sub = extract_bracketed($params, '()'); + push @mono_params, "repr($sub)"; + next; + } + if ($params =~ s/^mono_any//) { + push @mono_params, "any"; + next; + } + last; + } + + my @key_params; + for (my $i = 0; $i < @mono_params; ++$i) { + if ($mono_params[$i] eq 'precise') { + push @key_params, 'precise(' . $real_substs[$i] . ')'; + } else { + push @key_params, $mono_params[$i]; + } + } + + my $key = "$fn_id with " . (join ', ', @key_params); + $funcs{$key}{$real_substs} = 1; +} + +while (my ($key, $substs) = each %funcs) { + my @params = keys %$substs; + next if @params == 1; + + print "$key\n"; + print(('-' x (length $key)), $/); + for my $param (@params) { + print "$param\n"; + } + print "\n"; +} + diff --git a/src/librustc/middle/trans/type_use.rs b/src/librustc/middle/trans/type_use.rs index dedf667a4d93..33200a2dd828 100644 --- a/src/librustc/middle/trans/type_use.rs +++ b/src/librustc/middle/trans/type_use.rs @@ -192,11 +192,11 @@ fn node_type_needs(cx: ctx, use_: uint, id: node_id) { type_needs(cx, use_, ty::node_id_to_type(cx.ccx.tcx, id)); } -fn mark_for_method_call(cx: ctx, e_id: node_id) { +fn mark_for_method_call(cx: ctx, e_id: node_id, callee_id: node_id) { do option::iter(&cx.ccx.maps.method_map.find(e_id)) |mth| { match mth.origin { typeck::method_static(did) => { - do cx.ccx.tcx.node_type_substs.find(e_id).iter |ts| { + do cx.ccx.tcx.node_type_substs.find(callee_id).iter |ts| { let type_uses = type_uses_for(cx.ccx, did, ts.len()); for vec::each2(type_uses, *ts) |uses, subst| { type_needs(cx, *uses, *subst) @@ -269,7 +269,7 @@ fn mark_for_expr(cx: ctx, e: @expr) { // the chosen field. let base_ty = ty::node_id_to_type(cx.ccx.tcx, base.id); type_needs(cx, use_repr, ty::type_autoderef(cx.ccx.tcx, base_ty)); - mark_for_method_call(cx, e.id); + mark_for_method_call(cx, e.id, e.callee_id); } expr_log(_, _, val) => { node_type_needs(cx, use_tydesc, val.id); @@ -299,7 +299,7 @@ fn mark_for_expr(cx: ctx, e: @expr) { _ => () } } - mark_for_method_call(cx, e.id); + mark_for_method_call(cx, e.id, e.callee_id); } expr_paren(e) => mark_for_expr(cx, e), expr_match(*) | expr_block(_) | expr_if(*) |